_.concat(array, [values])
3
_.concat(array, [values])
concat方法将传递的参数与源数组连接起来,需要连接的参数是数组或者值都可以,然后返回新数组。
参数
array (Array):需要连接的源数组
[values] (...*):需要连接到源数组的参数
返回值
(Array):连接好的新数组
例子
var array = [1]; var other = _.concat(array, 2, [3], [[4]]); console.log(other); // => [1, 2, 3, [4]] console.log(array); // => [1]
源代码:
/** * lodash (Custom Build) <https://lodash.com/> * Build: `lodash modularize exports="npm" -o ./` * Copyright jQuery Foundation and other contributors <https://jquery.org/> * Released under MIT license <https://lodash.com/license> * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ /** Used as references for various `Number` constants. */ var MAX_SAFE_INTEGER = 9007199254740991; /** `Object#toString` result references. */ var argsTag = '[object Arguments]', funcTag = '[object Function]', genTag = '[object GeneratorFunction]'; /** Detect free variable `global` from Node.js. */ var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; /** Detect free variable `self`. */ var freeSelf = typeof self == 'object' && self && self.Object === Object && self; /** Used as a reference to the global object. */ var root = freeGlobal || freeSelf || Function('return this')(); /** * Appends the elements of `values` to `array`. * * @private * @param {Array} array The array to modify. * @param {Array} values The values to append. * @returns {Array} Returns `array`. */ //将参数值添加入参数数组 function arrayPush(array, values) { var index = -1,//循环索引 length = values.length,//需要添加到源数组的参数 offset = array.length;//源数组的长度 while (++index < length) {//循环并讲参数一个一个加入源数组 array[offset + index] = values[index]; } return array; } /** Used for built-in method references. */ var objectProto = Object.prototype; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** * Used to resolve the * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ //Object.prototype.toString,用于判断数据类型 var objectToString = objectProto.toString; /** Built-in value references. */ var Symbol = root.Symbol, propertyIsEnumerable = objectProto.propertyIsEnumerable, spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined; /** * The base implementation of `_.flatten` with support for restricting flattening. * * @private * @param {Array} array The array to flatten. * @param {number} depth The maximum recursion depth. * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. * @param {Array} [result=[]] The initial result value. * @returns {Array} Returns the new flattened array. */ //这个方法用于数组展开 function baseFlatten(array, depth, predicate, isStrict, result) { //array需要展开操作的数组,depth需要展开的层数 //predicate用于判断值是否可展开 //isStrict标识用于判断是否约束值必须通过predicate方法的检查 var index = -1, length = array.length; //index循环索引,length,需要展开的数组的长度 predicate || (predicate = isFlattenable);//predicate每次循环都会调用,用来判断当前值是否是一个可展开的array-like对象 result || (result = []);//返回值数组 while (++index < length) { var value = array[index];//数组循环当前值 if (depth > 0 && predicate(value)) {//如果展开层数大于0且当前循环值可展开 if (depth > 1) {//如果展开层数大于1就进行递归调用 // Recursively flatten arrays (susceptible to call stack limits). baseFlatten(value, depth - 1, predicate, isStrict, result); } else {//如果只展开一层 arrayPush(result, value); } } else if (!isStrict) {//如果没有传递isStrict标识,就直接讲当前循环值push入结果数组 result[result.length] = value; } } return result; } /** * Copies the values of `source` to `array`. * * @private * @param {Array} source The array to copy values from. * @param {Array} [array=[]] The array to copy values to. * @returns {Array} Returns `array`. */ //根据源数组克隆生成一个新的数组 function copyArray(source, array) {//source源数组,array目标数组 var index = -1,//循环索引 length = source.length;//源数组长度 array || (array = Array(length));//如果没有传递目标数组就新建一个,长度和源数组一样 while (++index < length) {//循环 array[index] = source[index];//给新数组赋值 } return array;//返回复制的新数组 } /** * Checks if `value` is a flattenable `arguments` object or array. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. */ //检查一个变量是否是一个可展开的对象或者数组 function isFlattenable(value) { return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]); //如果是数组,则可展开 //如果是arguments对象,则可展开 //如果当前环境含有Symbol对象,且此变量含有Symbol.isConcatSpreadable属性,Symbol.isConcatSpreadable用于改变array或者array-like对象使用concat时的默认行为 } /** * Creates a new array concatenating `array` with any additional arrays * and/or values. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to concatenate. * @param {...*} [values] The values to concatenate. * @returns {Array} Returns the new concatenated array. * @example * * var array = [1]; * var other = _.concat(array, 2, [3], [[4]]); * * console.log(other); * // => [1, 2, 3, [4]] * * console.log(array); * // => [1] */ //创建一个新数组,把array和任何提供的值或者数组连接起来 function concat() { var length = arguments.length,//参数的长度 args = Array(length ? length - 1 : 0),//新建args数组用来存放除array之外其他所有供连接的参数 array = arguments[0],//array index = length;//参数长度 while (index--) {//循环,将args数组存上这些供连接的参数 args[index - 1] = arguments[index]; } return length ? arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)) : []; //arrayPush传递两个参数 //第一个参数是复制一份源数组array,判断array是否是数组,如果是就copy一份,如果不是数组,就生成一个存着array值得新数组 //第二个参数是展开一层后的参数数组 } /** * Checks if `value` is likely an `arguments` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an `arguments` object, * else `false`. * @example * * _.isArguments(function() { return arguments; }()); * // => true * * _.isArguments([1, 2, 3]); * // => false */ //判断一个变量是否是一个arguments对象 function isArguments(value) { // Safari 8.1 makes `arguments.callee` enumerable in strict mode. return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); //是否是array-like对象,是否拥有callee属性,callee属性是否可枚举,Object.prototype.toString返回Arguments类型 } /** * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an array, else `false`. * @example * * _.isArray([1, 2, 3]); * // => true * * _.isArray(document.body.children); * // => false * * _.isArray('abc'); * // => false * * _.isArray(_.noop); * // => false */ //判断一个变量是否是数组 var isArray = Array.isArray; /** * Checks if `value` is array-like. A value is considered array-like if it's * not a function and has a `value.length` that's an integer greater than or * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is array-like, else `false`. * @example * * _.isArrayLike([1, 2, 3]); * // => true * * _.isArrayLike(document.body.children); * // => true * * _.isArrayLike('abc'); * // => true * * _.isArrayLike(_.noop); * // => false */ //判断一个变量是否是一个array-like对象。规则:不是function,拥有length属性,length属性值是整数,大于等于0,小于等于Number.MAX_SAFE_INTEGER function isArrayLike(value) { return value != null && isLength(value.length) && !isFunction(value); } /** * This method is like `_.isArrayLike` except that it also checks if `value` * is an object. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an array-like object, * else `false`. * @example * * _.isArrayLikeObject([1, 2, 3]); * // => true * * _.isArrayLikeObject(document.body.children); * // => true * * _.isArrayLikeObject('abc'); * // => false * * _.isArrayLikeObject(_.noop); * // => false */ //判断一个变量是否是一个array-like对象 function isArrayLikeObject(value) { return isObjectLike(value) && isArrayLike(value); } /** * Checks if `value` is classified as a `Function` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a function, else `false`. * @example * * _.isFunction(_); * // => true * * _.isFunction(/abc/); * // => false */ //判断一个变量是否是一个function对象 function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in Safari 8-9 which returns 'object' for typed array and other constructors. var tag = isObject(value) ? objectToString.call(value) : ''; //如果变量是一个对象,就用Object.prototype.toString来获取它的类型字符串 return tag == funcTag || tag == genTag;//是否是Function类型或者GeneratorFunction } /** * Checks if `value` is a valid array-like length. * * **Note:** This method is loosely based on * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. * @example * * _.isLength(3); * // => true * * _.isLength(Number.MIN_VALUE); * // => false * * _.isLength(Infinity); * // => false * * _.isLength('3'); * // => false */ //判断一个变量是否是一个array-like对象的有效length属性 function isLength(value) { return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; //变量是number类型,大于-1,是整数,小于Number.MAX_SAFE_INTEGER } /** * Checks if `value` is the * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * _.isObject({}); * // => true * * _.isObject([1, 2, 3]); * // => true * * _.isObject(_.noop); * // => true * * _.isObject(null); * // => false */ //判断一个变量是否是object类型 function isObject(value) { var type = typeof value; return !!value && (type == 'object' || type == 'function'); } /** * Checks if `value` is object-like. A value is object-like if it's not `null` * and has a `typeof` result of "object". * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. * @example * * _.isObjectLike({}); * // => true * * _.isObjectLike([1, 2, 3]); * // => true * * _.isObjectLike(_.noop); * // => false * * _.isObjectLike(null); * // => false */ //判断一个变量是否是一个object-like对象,规则:不是null且typeof返回object function isObjectLike(value) { return !!value && typeof value == 'object'; } module.exports = concat;