You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环赋值右侧先求值?arrayToList函数链表构建原理解惑

搞懂数组转链表的循环逻辑

我在理解一段数组转链表的代码时遇到了困惑,就是下面这段函数:

function arrayToList(array) { 
  var list = null; 
  for (var i = array.length-1; i>=0; i--) { 
    list = {value: array[i], rest: list}; 
  } 
  return list; 
}

我的疑问是:为什么已有的list没有被新list覆盖,反而新list能把旧的list存入自己的rest属性中?

原问题的选中答案评论里给出了这样的解释:

因为赋值操作的整个右侧表达式会在实际赋值给左侧变量前完成求值/执行。因此在构建新对象时,旧对象不会被修改,其值可用于新对象的构建。就像var a = 1; a = 1 + a;执行后a的值为2,在右侧表达式求值完成前,a的值不会改变。list的情况同理,我们并非修改list,而是改变它所引用的对象。例如,它原本引用{value: 3, rest: null},现在引用新对象{value: 2, rest: {value: 3, rest: null}}。

我当时没看明白,现在用更直白的方式拆解给你:

其实核心就是赋值的执行顺序——JavaScript会先把赋值符号=右侧的所有表达式计算完,再把结果赋值给左侧的变量。咱们拿具体的数组[1,2,3]一步步走循环,就能看清逻辑:

  • 第一次循环(i=2,对应数组元素3):
    先计算右侧的对象:{value: 3, rest: list},这时候list还是初始的null,所以这个新对象是{value: 3, rest: null}。之后把这个对象赋值给list,现在list就指向这个对象了。

  • 第二次循环(i=1,对应数组元素2):
    还是先算右侧:{value: 2, rest: list},此时list指向的是上一步的{value: 3, rest: null},所以新对象的rest直接引用这个旧对象。然后把新对象赋值给list,现在list的指向变成了{value: 2, rest: {value: 3, rest: null}}。

  • 第三次循环(i=0,对应数组元素1):
    右侧计算时,list指向的是第二步的对象,所以新对象的rest就是这个对象。赋值完成后,list就成了最终的链表头部:{value: 1, rest: {value: 2, rest: {value: 3, rest: null}}}。

你看,每次循环都不是“修改旧的list对象”,而是用旧list的当前值创建一个全新的对象,然后让list变量转而指向这个新对象。旧的对象并没有被覆盖或删除,它被新对象的rest属性引用着,所以就像链条一样串了起来,这也是为什么循环看起来像递归一样层层嵌套,而不是把list给重写没了。

内容的提问来源于stack exchange,提问作者Ismail Armouti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:54:34