lodash源码之baseFlatten的一些疑问

业务背景

其实没有啥业务背景,就是学习源码,看看高手怎么写的,为了保持自己提问的风格,还是把这一段加上吧

问题描述

在源码倒数第4行,为什么要使用下标添加元素呢result[result.length] = value,使用push看上去应该更简洁呀

并且倒数第8行,也是使用的push啊

开始还以为是性能问题,但测试后发现,两者给数组添加元素的耗时是差不多的呀,所以排除性能原因

后台又以为是为了兼容低版本浏览器而拒绝使用push,但是看以这里,他自己也在使用,所以也排除是兼容问题

那到底为什么要使用下标的方式,给数组添加单个元素呢?

源码

  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
}
阅读 2.3k
1 个回答

发现你是看的github仓库里的代码 lodash baseFlatten

实际上打包后的代码是这样的。

function baseFlatten(array, depth, predicate, isStrict, result) {
    var index = -1,
        length = array.length;

    predicate || (predicate = isFlattenable);
    result || (result = []);

    while (++index < length) {
      var value = array[index];
      if (depth > 0 && predicate(value)) {
        if (depth > 1) {
          // Recursively flatten arrays (susceptible to call stack limits).
          baseFlatten(value, depth - 1, predicate, isStrict, result);
        } else {
          arrayPush(result, value);
        }
      } else if (!isStrict) {
        result[result.length] = value;
      }
    }
    return result;
  }

我看的 lodash 的 v4.17.15 版本。
打包后并没有用数组原生的push呀。而是内部实现的arrayPush。主要还是由于性能考虑。

V8引擎代码还有一次循环。

// 看看V8引擎中的具体push实现:
function ArrayPush() {
    var n = TO_UINT32( this.length );    // 被push的对象的length
    var m = %_ArgumentsLength();     // push的参数个数
    for (var i = 0; i < m; i++) {
        this[ i + n ] = %_Arguments( i );   // 复制元素     (1)
    }
    this.length = n + m;      // 修正length属性的值    (2)
    return this.length;
};

这段V8引擎是引用自我的文章。
面试官问:能否模拟实现JS的call和apply方法

也就是说单个数量没使用push没使用循环。多个push(...value),最终还是需要转换的。

看lodash源码,可以看我的这篇文章呀。学习 lodash 源码整体架构,打造属于自己的函数式编程类库

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏