首页 > 解决方案 > 在 JavaScript 中,分配给变量的对象如何跟踪未来的突变?

问题描述

我最近一直在用 JavaScript 练习数据结构,我发现了一段我无法理解的代码片段。我知道,当您将对象分配给变量,然后对对象进行变异时,原始变量可以“看到”这些变异,因为当您将对象分配给变量时,您并没有克隆对象,您只是传递了一个引用它。但是,下面的代码让我感到困惑:

function ListNode(val, next) {
  this.val = (val === undefined ? 0 : val)
  this.next = (next === undefined ? null : next)
}

let tempList = [1, 1, 2, 4, 4, 100];

let point = new ListNode(tempList[0]);
let head = point;

for (let i = 1; i < tempList.length; i++) {
  point.next = new ListNode(tempList[i])
  point = point.next;
}

console.log(head); // Outputs the Linked List 1 -> 1 -> 2 -> 4 -> 4 -> 100

因此,当我尝试遵循脑海中的逻辑时,我将其描绘如下:

在第一次迭代中,headpoint保存以下信息:

{
  val: 1,
  next: null
}

在第二次迭代中,point首先保存以下信息:

{
  val: 1,
  next: {
    val: 1,
    next: null
  }
}

也是如此head,但是下一步让我感到困惑。在我的脑海中,我在point之前的步骤中用新创建的节点覆盖了当前值,所以变量应该如下所示:

{
  val: 1,
  next: null
}

并且head因为它只是持有一个参考point应该看起来像那样。但是,head看起来如下:

{
  val: 1,
  next: {
    val: 1,
    next: null
  }
}

并且随着迭代的继续进行,显然,head会跟踪所有链接的节点。这是期望的行为,但我不完全理解这是如何发生的。有人可以解释一下为什么会这样吗?

标签: javascriptdata-structureslinked-list

解决方案


在 JavaScript 中,变量不绑定到其他变量。它们绑定到当时变量的,在您的情况下是初始point对象。

听起来你的心智模型告诉你 head-> point-> {} 实际上两者都指向同一个对象,因此绑定point到新对象不会影响head

head不在循环中,因此head一旦将其绑定到绑定的第一个对象,您就永远不会真正更新它的值point


推荐阅读