为何引用同一dummy对象的fast/slow指针修改slow不影响fast?
JavaScript对象引用与变量赋值的本质——以快慢指针为例
在下面这段删除链表倒数第N个节点的JavaScript代码中,slow和fast初始都指向同一个dummy对象,但执行slow = slow.next后,fast完全没受影响。为什么会出现这种情况?
function ListNode(val, next) { this.val = (val === undefined ? 0 : val) this.next = (next === undefined ? null : next) } var removeNthFromEnd = function(head, n) { let dummy = new ListNode(0); dummy.next = head; let slow = dummy; let fast = dummy; slow = slow.next console.log(fast) for (let i = 0; i <= n; i++) { fast = fast.next; } while (fast !== null) { slow = slow.next; fast = fast.next; } return dummy.next; }; removeNthFromEnd({ val: 1, next: { val: 2, next: { val: 3, next: { val: 4, next: { val: 5, next: null } } } } }, 2)
核心原因:变量存的是对象引用地址,而非对象本身
JavaScript里的对象存储在堆内存中,变量只是保存了指向该对象的内存地址。这里的变量重新赋值和对象属性修改是完全不同的操作:
初始阶段:
let slow = dummy; let fast = dummy;
此时slow和fast两个变量保存的是同一个内存地址,指向堆里的dummy对象。如果这时候修改对象的属性(比如slow.next = new ListNode(6)),因为指向同一个对象,fast.next也会看到这个变化。执行
slow = slow.next时:
这是给slow变量重新赋值——把slow里的地址替换成slow.next指向的节点的内存地址。而fast变量里保存的还是原来dummy对象的地址,自然不会受到影响。
简单对比示例
let obj1 = {a: 1}; let obj2 = obj1; // 修改对象属性:两个变量指向同一对象,都会变化 obj1.a = 2; console.log(obj2.a); // 输出 2 // 重新赋值变量:obj2指向原对象,不受影响 obj1 = {b: 3}; console.log(obj2); // 输出 {a: 2}
回到链表代码,slow = slow.next就是典型的变量重新赋值操作,只是改变了slow的指向地址,并没有修改原dummy对象的内容,所以fast的指向完全不会跟着改变。
内容的提问来源于stack exchange,提问作者suresh subedi
相关产品推荐
相关产品推荐

