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

链表append()方法覆盖this.tail时仍可更新嵌套节点的原理疑问

核心前提:JS 基础类型与引用类型的赋值逻辑差异

你观察到的两种不同表现,本质是JS中两类数据类型的赋值规则不同:

  • 基础类型(Number、String、Boolean等):赋值时直接拷贝值,两个变量存储在栈内存中完全独立,修改一个不会影响另一个。
  • 引用类型(对象、数组等):赋值时拷贝的是堆内存的存储地址,多个变量可以指向同一个堆内存中的对象,修改对象的属性会同步到所有指向该对象的变量上。

第一个示例的运行逻辑

你写的potatoes和fish操作的是基础类型,所以修改不联动是正常表现:

let potatoes = 5 // 栈内存中存入值5,变量potatoes指向该值
let fish = potatoes // 拷贝potatoes的*值*给fish,fish在栈中独立存了一份5
potatoes = 2 // 修改potatoes指向的栈值为2,和fish完全无关
console.log(fish) // 输出5

链表append方法的逐行拆解

链表中的所有节点都是引用类型的对象,我们以第一次调用append(2)的完整流程为例:

  1. 构造函数执行完成时:
    堆内存中生成地址为0x001的节点对象:{value:5, next:null}
    this.head存储的地址是0x001,this.tail = this.head表示this.tail也存储地址0x001,两个变量指向同一个堆对象。
  2. 调用append(2)生成新节点:
    堆内存中生成地址为0x002的新节点:{value:2, next:null},赋值给变量newNode
  3. 执行this.tail.next = newNode:
    此时this.tail存的是0x001,这行代码等价于直接修改地址为0x001的堆对象的next属性,赋值为0x002,此时head节点的next已经指向新节点,该修改是直接作用在堆对象上的,和后续this.tail的变化无关。
  4. 执行this.tail = newNode:
    这步只是修改this.tail这个变量本身存储的地址,从0x001改成0x002,完全不会触碰0x001这个堆对象的内容,也不会修改this.head存储的地址,所以不可能覆盖head。
  5. 后续调用append的逻辑完全一致:每次都是先通过this.tail找到当前尾节点的堆地址,修改它的next属性指向新节点,再把this.tail的地址改成新节点的地址即可。

常见疑问解答

  • this.tail.next是如何同时更新this.tail和它所指向的对象的?
    并没有同时更新两者,this.tail.next修改的是this.tail当前指向的堆对象的属性,this.tail本身存储的地址没有变化,直到下一行代码才会修改this.tail本身的指向。
  • 为什么把this.tail覆盖为newNode不会把this.head整个覆盖?
    this.tail和this.head是两个独立的变量,只是初始阶段指向同一个堆对象,修改this.tail本身存储的地址,完全不会影响this.head存储的地址,也不会修改之前指向的堆对象的内容。
  • 我们只设置了this.tail.next,没有直接操作原节点引用,为什么原引用的next属性会被更新?
    因为this.tail存储的就是原节点的堆地址,this.tail.next就是直接操作原节点的属性,你所谓的“原引用”和this.tail指向同一个堆对象,所以修改会同步生效。

完整可运行代码

class LinkedList {
  constructor(value) {
    this.head = {
      value,
      next: null
    }
    this.tail = this.head
    this.length = 1
  }
  append(value) {
    const newNode = {
      value,
      next: null
    }
    this.tail.next = newNode
    this.tail = newNode
    this.length++
    return this
  }
 }
 
const linkedList = new LinkedList(5)
linkedList.append(2)
linkedList.append(8)

console.log(linkedList)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:15:07