JavaScript链表构建中head引用变化及指向尾节点的原理问询
链表代码执行过程解析
先看目标代码:
let head = { val: 0, next: null }; let list = head; const arr = [1, 2, 3, 4]; for (let c of arr) { list.next = { val: c, next: null }; list = list.next; } console.log(head);
问题与解答
1. 整个过程的具体执行步骤是怎样的?
- 初始阶段:创建初始对象
{ val: 0, next: null },变量head和list的栈内存中都存储该对象的引用地址,二者指向同一个对象。 - 循环遍历数组(共4次):
- 第一次循环(c=1):
- 给当前
list指向的对象的next属性赋值新对象{ val: 1, next: null },此时初始对象变为{ val: 0, next: { val: 1, next: null } },head因指向初始对象,自然能访问到更新后的结构。 - 将
list重新赋值为list.next,也就是刚创建的{ val: 1, next: null },此时list的引用切换到这个新节点,head仍指向初始头节点。
- 给当前
- 第二次循环(c=2):
- 给当前
list指向的{ val: 1, next: null }的next属性赋值{ val: 2, next: null },链表结构延伸为{ val: 0, next: { val: 1, next: { val: 2, next: null } } }。 list更新为这个新的{ val: 2, next: null }节点。
- 给当前
- 第三次循环(c=3):
- 给
list指向的{ val: 2, next: null }的next赋值{ val: 3, next: null },链表继续扩展。 list切换到这个新节点。
- 给
- 第四次循环(c=4):
- 给
list指向的{ val: 3, next: null }的next赋值{ val: 4, next: null },最终链表完整结构为:{ val: 0, next: { val: 1, next: { val: 2, next: { val: 3, next: { val: 4, next: null } } } } } list切换到这个尾节点{ val: 4, next: null }。
- 给
- 第一次循环(c=1):
- 最终输出:执行
console.log(head),输出的是初始头节点对象,通过它的next属性可以遍历整个链表。
2. 执行过程中是否存在引用变化?
head的引用全程不变:它始终指向最初创建的{ val: 0, next: null }对象,只是该对象的next属性被不断修改,指向新的子节点。list的引用每次循环都会改变:初始和head指向同一对象,每次循环后半段都会把list的引用更新为刚创建的新节点,直到最后指向链表的尾节点。
3. 为何head变量最终指向的是尾节点?
这是一个误解:head自始至终都指向链表的头节点(即最初的{ val: 0, next: null })。你看到console.log(head)输出包含整个链表,是因为头节点的next属性链接着所有后续节点,并非head指向了尾节点。真正指向尾节点的是list,因为每次循环都将它移动到下一个新节点。
内容的提问来源于stack exchange,提问作者Nazmul Islam Nahid
相关产品推荐
相关产品推荐

