• lodash compact & concat


    前置

    本篇随笔包含 _.compact_.concat 及其依赖的工具函数。

    你可能需要一些 JavaScript 基础知识才能看懂一些没有注释的细节。

    compact

    _.compact(array)
    

    创建一个新数组,包含原数组中所有的非假值元素。例如 false, null, 0, "", undefined, 和 NaN 都是被认为是“假值”。

    /**
     * Creates an array with all falsey values removed. The values `false`, `null`,
     * `0`, `""`, `undefined`, and `NaN` are falsey.
     *
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to compact.
     * @returns {Array} Returns the new array of filtered values.
     * @example
     *
     * compact([0, 1, false, 2, '', 3])
     * // => [1, 2, 3]
     */
    function compact(array) {
      let resIndex = 0
      const result = []
    
      if (array == null) {
        return result
      }
    
      // for of 循环 array
      // resIndex 自增赋值符合条件的数组
      for (const value of array) {
        if (value) {
          result[resIndex++] = value
        }
      }
      return result
    }
    
    export default compact
    

    arrayPush

    /**
     * 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;
    
      // 循环往array结尾追加values的元素
      while (++index < length) {
        array[offset + index] = values[index];
      }
      return array;
    }
    
    module.exports = arrayPush;
    
    

    对比 v8 的 push 实现:

    // Appends the arguments to the end of the array and returns the new
    // length of the array. See ECMA-262, section 15.4.4.7.
    function ArrayPush() {
      CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push");
    
      var array = TO_OBJECT(this);
      var n = TO_LENGTH(array.length); // 被push的array的length
      var m = arguments.length;
    
      // Subtract n from kMaxSafeInteger rather than testing m + n >
      // kMaxSafeInteger. n may already be kMaxSafeInteger. In that case adding
      // e.g., 1 would not be safe.
      if (m > kMaxSafeInteger - n) throw %make_type_error(kPushPastSafeLength, m, n);
    
      for (var i = 0; i < m; i++) {
        array[i+n] = arguments[i]; // 复制元素
      }
    
      var new_length = n + m; // 修正length属性的值
      array.length = new_length;
      return new_length;
    }
    

    isObjectLike

    检查 value 是否是类对象。如果一个值不是 null,并且 typeof 结果为 object,则该值为类对象。

    /**
     * Checks if `value` is object-like. A value is object-like if it's not `null`
     * and has a `typeof` result of "object".
     *
     * @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(Function)
     * // => false
     *
     * isObjectLike(null)
     * // => false
     */
    function isObjectLike(value) {
      return typeof value === 'object' && value !== null
    }
    
    export default isObjectLike
    

    isArguments

    import getTag from './.internal/getTag.js' // 在上一篇文章中解释了这个方法
    import isObjectLike from './isObjectLike.js'
    
    /**
     * Checks if `value` is likely an `arguments` object.
     *
     * @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
     */
    function isArguments(value) {
      // 已经解释过 toStringTag
      return isObjectLike(value) && getTag(value) == '[object Arguments]'
    }
    
    export default isArguments
    

    isFlattenable

    检查 value 是否为可扁平化的 arguments 对象或数组。

    import isArguments from '../isArguments.js'
    
    /** Built-in value reference. */
    const spreadableSymbol = Symbol.isConcatSpreadable
    
    /**
     * 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) {
      // Symbol.isConcatSpreadable 用于配置某对象作为 Array.prototype.concat() 方法的参数时是否展开其数组元素。
      // 参考 https://segmentfault.com/q/1010000021953491 的采纳答案
      return Array.isArray(value) || isArguments(value) ||
        !!(value && value[spreadableSymbol])
    }
    
    export default isFlattenable
    

    baseFlatten

    import isFlattenable from './isFlattenable.js'
    
    /**
     * 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. // 只限于通过 "predicate"检查的数值。
     * @param {Array} [result=[]] The initial result value. // 初始结果值
     * @returns {Array} Returns the new flattened array. // 返回新的扁平化数组。
     */
    function baseFlatten(array, depth, predicate, isStrict, result) {
      predicate || (predicate = isFlattenable)
      result || (result = [])
    
      if (array == null) {
        return result
      }
    
      for (const value of array) {
        if (depth > 0 && predicate(value)) {
          if (depth > 1) {
            // Recursively flatten arrays (susceptible to call stack limits).
            // 递归扁平化数组(易受调用栈限制)。
            baseFlatten(value, depth - 1, predicate, isStrict, result)
          } else {
            result.push(...value)
          }
        } else if (!isStrict) {
          result[result.length] = value
        }
      }
      return result
    }
    
    export default baseFlatten
    

    copyArray

    /**
     * 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) {
      let index = -1
      const length = source.length
    
      array || (array = new Array(length))
      while (++index < length) {
        array[index] = source[index]
      }
      return array
    }
    
    export default copyArray
    

    isArray

    /**
     * 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;
    
    module.exports = isArray;
    

    concat

    _.concat(array, [values])
    

    创建一个新数组,将 array 与任何数组或值连接在一起。

    var arrayPush = require('./_arrayPush'),
        baseFlatten = require('./_baseFlatten'), // 扁平化数组
        copyArray = require('./_copyArray'),
        isArray = require('./isArray');
    
    /**
     * 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]
     */
    function concat() {
      var length = arguments.length; // 参数数量
      if (!length) {
        return [];
      }
      var args = Array(length - 1), // [empty]
          array = arguments[0],  // 原数组
          index = length; 
    
      // args 加入除原数组以外的参数其他参数的数组或值
      while (index--) {
        args[index - 1] = arguments[index];
      }
      // 若原数组是 Array 类型,拷贝一遍数组返回,反之创建一个数组
      // 将 args 扁平化并 push 到原数组
      return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
    }
    
    module.exports = concat;
    
  • 相关阅读:
    scala学习资料
    maven安装scala插件
    关于 mod_python
    Python读取Excel数据
    Python展开一个嵌套的序列
    随手写的Java向文本文件写字符串的类
    Python三元表达式
    递归的概述
    一分钟让你明白CSS中的盒模型
    Python实现ID3算法
  • 原文地址:https://www.cnblogs.com/guangzan/p/13234694.html
Copyright © 2020-2023  润新知