首页 > 编程语言 > 详细

JavaScript 数组遍历动态增长问题(V8源码解析)

时间:2021-05-10 23:05:35      阅读:19      评论:0      收藏:0      [点我收藏+]

数组 arr 在遍历同时动态增长会发生什么呢

let arr = [1,2]
arr.forEach(item => arr.push(...arr))
console.log(arr)
// 输出: [ 1, 2, 1, 2, 1, 2, 1, 2 ]

并未输出 [1,2] 或 [1,2,1,2...] 无限循环下去

JavaScript引擎:V8源码git地址:https://github.com/v8/v8


vscode打开源码文件夹
技术分享图片

V8-MASTER/src/builtins-collections-gen.cc

数组的循环遍历由 Goto 与 BIND 搭配完成,Goto(adress) 指跳转的目标adress , BIND(adress) 指对应接受的目的地adress

TF_BUILTIN(MapPrototypeForEach, CollectionsBuiltinsAssembler) {
  const char* const kMethodName = "Map.prototype.forEach"; // Array 继承自 MapCollections
  ......
  // Ensure that {callback} is actually callable.
  Label callback_not_callable(this, Label::kDeferred);
  GotoIf(TaggedIsSmi(callback), &callback_not_callable);
  GotoIfNot(IsCallable(CAST(callback)), &callback_not_callable);

  TVARIABLE(IntPtrT, var_index, IntPtrConstant(0));
  TVARIABLE(OrderedHashMap, var_table,
            CAST(LoadObjectField(CAST(receiver), JSMap::kTableOffset)));
  Label loop(this, {&var_index, &var_table}), done_loop(this); // 记录了数组的初始信息,后期判断是否遍历结束的标志
  Goto(&loop);
  BIND(&loop);
  {
    // 中括号内的依然会执行,只是产生了一个块作用域
    // 代码快内部执行完后,会被回收资源
    // Transition {table} and {index} if there was any modification to
    // the {receiver} while we‘re iterating.
    TNode<IntPtrT> index = var_index.value();
    TNode<OrderedHashMap> table = var_table.value();
    std::tie(table, index) = Transition<OrderedHashMap>(
        table, index, [](const TNode<OrderedHashMap>, const TNode<IntPtrT>) {});

    // Read the next entry from the {table}, skipping holes.
    TNode<Object> entry_key;
    TNode<IntPtrT> entry_start_position;
    std::tie(entry_key, entry_start_position, index) =
        NextSkipHoles<OrderedHashMap>(table, index, &done_loop);

    // Load the entry value as well.
    TNode<Object> entry_value = LoadFixedArrayElement(
        table, entry_start_position,
        (OrderedHashMap::HashTableStartIndex() + OrderedHashMap::kValueOffset) *
            kTaggedSize);

    // Invoke the {callback} passing the {entry_key}, {entry_value} and the
    // {receiver}.
    Call(context, callback, this_arg, entry_value, entry_key, receiver);

    // Continue with the next entry.
    var_index = index;
    var_table = table;
    Goto(&loop);
  }
  BIND(&done_loop);
  args.PopAndReturn(UndefinedConstant());
  BIND(&callback_not_callable);
  ......
}

JavaScript 数组遍历动态增长问题(V8源码解析)

原文:https://www.cnblogs.com/lhx9527/p/14752681.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!