UNPKG

@segment/analytics.js-core

Version:

The hassle-free way to integrate analytics into any web application.

139 lines (138 loc) 4.81 kB
'use strict'; /* * The MIT License (MIT) * Copyright (c) 2015 Nathan Houle * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * Module dependencies. */ var keys = require('@ndhoule/keys'); var objToString = Object.prototype.toString; /** * Tests if a value is a number. * * @name isNumber * @api private * @param {*} val The value to test. * @return {boolean} Returns `true` if `val` is a number, otherwise `false`. */ var isNumber = function isNumber(val) { var type = typeof val; return (type === 'number' || (type === 'object' && objToString.call(val) === '[object Number]')); }; /** * Tests if a value is an array. * * @name isArray * @api private * @param {*} val The value to test. * @return {boolean} Returns `true` if the value is an array, otherwise `false`. */ var isArray = typeof Array.isArray === 'function' ? Array.isArray : function isArray(val) { return objToString.call(val) === '[object Array]'; }; /** * Tests if a value is array-like. Array-like means the value is not a function and has a numeric * `.length` property. * * @name isArrayLike * @api private * @param {*} val * @return {boolean} */ var isArrayLike = function isArrayLike(val) { return (val != null && (isArray(val) || (val !== 'function' && isNumber(val.length)))); }; /** * Internal implementation of `each`. Works on arrays and array-like data structures. * * @name arrayEach * @api private * @param {Function(value, key, collection)} iterator The function to invoke per iteration. * @param {Array} array The array(-like) structure to iterate over. * @return {undefined} */ var arrayEach = function arrayEach(iterator, array) { for (var i = 0; i < array.length; i += 1) { // Break iteration early if `iterator` returns `false` if (iterator(array[i], i, array) === false) { break; } } }; /** * Internal implementation of `each`. Works on objects. * * @name baseEach * @api private * @param {Function(value, key, collection)} iterator The function to invoke per iteration. * @param {Object} object The object to iterate over. * @return {undefined} */ var baseEach = function baseEach(iterator, object) { var ks = keys(object); for (var i = 0; i < ks.length; i += 1) { // Break iteration early if `iterator` returns `false` if (iterator(object[ks[i]], ks[i], object) === false) { break; } } }; /** * Iterate over an input collection, invoking an `iterator` function for each element in the * collection and passing to it three arguments: `(value, index, collection)`. The `iterator` * function can end iteration early by returning `false`. * * @name each * @api public * @param {Function(value, key, collection)} iterator The function to invoke per iteration. * @param {Array|Object|string} collection The collection to iterate over. * @return {undefined} Because `each` is run only for side effects, always returns `undefined`. * @example * var log = console.log.bind(console); * * each(log, ['a', 'b', 'c']); * //-> 'a', 0, ['a', 'b', 'c'] * //-> 'b', 1, ['a', 'b', 'c'] * //-> 'c', 2, ['a', 'b', 'c'] * //=> undefined * * each(log, 'tim'); * //-> 't', 2, 'tim' * //-> 'i', 1, 'tim' * //-> 'm', 0, 'tim' * //=> undefined * * // Note: Iteration order not guaranteed across environments * each(log, { name: 'tim', occupation: 'enchanter' }); * //-> 'tim', 'name', { name: 'tim', occupation: 'enchanter' } * //-> 'enchanter', 'occupation', { name: 'tim', occupation: 'enchanter' } * //=> undefined */ var each = function each(iterator, collection) { return (isArrayLike(collection) ? arrayEach : baseEach).call(this, iterator, collection); }; /* * Exports. */ module.exports = each;