lodash源码之baseFlatten的一些疑问

发布于 2022-09-12 01:08:51 字数 937 浏览 11 评论 0

业务背景

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

问题描述

在源码倒数第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
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦冥 2022-09-19 01:08:51

发现你是看的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 源码整体架构,打造属于自己的函数式编程类库

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文