/** * @fileoverview This module has some functions for handling object as collection. * @author NHN. * FE Development Lab */ 'use strict'; var type = require('./type'); var object = require('./object'); /** * Execute the provided callback once for each element present * in the array(or Array-like object) in ascending order.
* If the callback function returns false, the loop will be stopped.
* Callback function(iteratee) is invoked with three arguments: * - The value of the element * - The index of the element * - The array(or Array-like object) being traversed * @param {Array} arr The array(or Array-like object) that will be traversed * @param {function} iteratee Callback function * @param {Object} [context] Context(this) of callback function * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * var sum = 0; * * util.forEachArray([1,2,3], function(value){ * sum += value; * }); * alert(sum); // 6 */ function forEachArray(arr, iteratee, context) { var index = 0; var len = arr.length; context = context || null; for (; index < len; index += 1) { if (iteratee.call(context, arr[index], index, arr) === false) { break; } } } /** * Execute the provided callback once for each property of object which actually exist.
* If the callback function returns false, the loop will be stopped.
* Callback function(iteratee) is invoked with three arguments: * - The value of the property * - The name of the property * - The object being traversed * @param {Object} obj The object that will be traversed * @param {function} iteratee Callback function * @param {Object} [context] Context(this) of callback function * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * var sum = 0; * * util.forEachOwnProperties({a:1,b:2,c:3}, function(value){ * sum += value; * }); * alert(sum); // 6 **/ function forEachOwnProperties(obj, iteratee, context) { var key; context = context || null; for (key in obj) { if (obj.hasOwnProperty(key)) { if (iteratee.call(context, obj[key], key, obj) === false) { break; } } } } /** * Execute the provided callback once for each property of object(or element of array) which actually exist.
* If the object is Array-like object(ex-arguments object), It needs to transform to Array.(see 'ex2' of example).
* If the callback function returns false, the loop will be stopped.
* Callback function(iteratee) is invoked with three arguments: * - The value of the property(or The value of the element) * - The name of the property(or The index of the element) * - The object being traversed * @param {Object} obj The object that will be traversed * @param {function} iteratee Callback function * @param {Object} [context] Context(this) of callback function * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * var sum = 0; * * util.forEach([1,2,3], function(value){ * sum += value; * }); * alert(sum); // 6 * * // In case of Array-like object * var array = Array.prototype.slice.call(arrayLike); // change to array * util.forEach(array, function(value){ * sum += value; * }); */ function forEach(obj, iteratee, context) { if (type.isArray(obj)) { forEachArray(obj, iteratee, context); } else { forEachOwnProperties(obj, iteratee, context); } } /** * Execute the provided callback function once for each element in an array, in order, * and constructs a new array from the results.
* If the object is Array-like object(ex-arguments object), * It needs to transform to Array.(see 'ex2' of forEach example)
* Callback function(iteratee) is invoked with three arguments: * - The value of the property(or The value of the element) * - The name of the property(or The index of the element) * - The object being traversed * @param {Object} obj The object that will be traversed * @param {function} iteratee Callback function * @param {Object} [context] Context(this) of callback function * @returns {Array} A new array composed of returned values from callback function * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * var result = util.map([0,1,2,3], function(value) { * return value + 1; * }); * * alert(result); // 1,2,3,4 */ function map(obj, iteratee, context) { var resultArray = []; context = context || null; forEach(obj, function() { resultArray.push(iteratee.apply(context, arguments)); }); return resultArray; } /** * Execute the callback function once for each element present in the array(or Array-like object or plain object).
* If the object is Array-like object(ex-arguments object), * It needs to transform to Array.(see 'ex2' of forEach example)
* Callback function(iteratee) is invoked with four arguments: * - The previousValue * - The currentValue * - The index * - The object being traversed * @param {Object} obj The object that will be traversed * @param {function} iteratee Callback function * @param {Object} [context] Context(this) of callback function * @returns {*} The result value * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * var result = util.reduce([0,1,2,3], function(stored, value) { * return stored + value; * }); * * alert(result); // 6 */ function reduce(obj, iteratee, context) { var index = 0; var keys, length, store; context = context || null; if (!type.isArray(obj)) { keys = object.keys(obj); length = keys.length; store = obj[keys[index += 1]]; } else { length = obj.length; store = obj[index]; } index += 1; for (; index < length; index += 1) { store = iteratee.call(context, store, obj[keys ? keys[index] : index]); } return store; } /** * Transform the Array-like object to Array.
* In low IE (below 8), Array.prototype.slice.call is not perfect. So, try-catch statement is used. * @param {*} arrayLike Array-like object * @returns {Array} Array * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * var arrayLike = { * 0: 'one', * 1: 'two', * 2: 'three', * 3: 'four', * length: 4 * }; * var result = util.toArray(arrayLike); * * alert(result instanceof Array); // true * alert(result); // one,two,three,four */ function toArray(arrayLike) { var arr; try { arr = Array.prototype.slice.call(arrayLike); } catch (e) { arr = []; forEachArray(arrayLike, function(value) { arr.push(value); }); } return arr; } /** * Create a new array or plain object with all elements(or properties) * that pass the test implemented by the provided function.
* Callback function(iteratee) is invoked with three arguments: * - The value of the property(or The value of the element) * - The name of the property(or The index of the element) * - The object being traversed * @param {Object} obj Object(plain object or Array) that will be traversed * @param {function} iteratee Callback function * @param {Object} [context] Context(this) of callback function * @returns {Object} plain object or Array * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * var result1 = util.filter([0,1,2,3], function(value) { * return (value % 2 === 0); * }); * alert(result1); // [0, 2] * * var result2 = util.filter({a : 1, b: 2, c: 3}, function(value) { * return (value % 2 !== 0); * }); * alert(result2.a); // 1 * alert(result2.b); // undefined * alert(result2.c); // 3 */ function filter(obj, iteratee, context) { var result, add; context = context || null; if (!type.isObject(obj) || !type.isFunction(iteratee)) { throw new Error('wrong parameter'); } if (type.isArray(obj)) { result = []; add = function(subResult, args) { subResult.push(args[0]); }; } else { result = {}; add = function(subResult, args) { subResult[args[1]] = args[0]; }; } forEach(obj, function() { if (iteratee.apply(context, arguments)) { add(result, arguments); } }, context); return result; } /** * fetching a property * @param {Array} arr target collection * @param {String|Number} property property name * @returns {Array} * @memberof tui.util * @example * //-- #1. Get Module --// * var util = require('tui-code-snippet'); // node, commonjs * var util = tui.util; // distribution file * * //-- #2. Use property --// * var objArr = [ * {'abc': 1, 'def': 2, 'ghi': 3}, * {'abc': 4, 'def': 5, 'ghi': 6}, * {'abc': 7, 'def': 8, 'ghi': 9} * ]; * var arr2d = [ * [1, 2, 3], * [4, 5, 6], * [7, 8, 9] * ]; * util.pluck(objArr, 'abc'); // [1, 4, 7] * util.pluck(arr2d, 2); // [3, 6, 9] */ function pluck(arr, property) { var result = map(arr, function(item) { return item[property]; }); return result; } module.exports = { forEachOwnProperties: forEachOwnProperties, forEachArray: forEachArray, forEach: forEach, toArray: toArray, map: map, reduce: reduce, filter: filter, pluck: pluck };