在这个问题中反转链表时,我遇到了一些奇怪的析构函数行为:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let previous = null
while (head) {
// Version 1 - works
[head.next, head, previous] = [previous, head.next, head]
// Version 2 - doesn't work
// [previous, head, head.next] = [head, head.next, previous]
// Version 3 - doesn't work
// [head, head.next, previous] = [head.next, previous, head]
}
return previous
};
我一辈子都不明白为什么破坏赋值v2和v3不起作用,而版本1起作用。head.next
分配导致问题。错误为:
Line 16 in solution.js
[previous, head, head.next] = [head, head.next, previous]
^
TypeError: Cannot set properties of null (setting 'next')
有人能解释版本1的工作方式吗?版本2和版本3没有?
如果将析构函数分解为单独的赋值,则更容易看出区别。
版本1相当于:
let temp = [previous, head.next, head]
head.next = temp[0];
head = temp[1];
previous = temp[2];
版本2相当于:
let temp = [head, head.next, previous]
previous = temp[0];
head = temp[1];
head.next = temp[2];
版本3:
let temp = [head.next, previous, head]
head = temp[0];
head.next = temp[1];
previous = temp[2];
在版本2和版本3中,您在重新分配head = head.next
之后分配head.next
。但是您需要更改原始head
节点的next
属性,而不是新节点。
如果最初的head.next
是null
,那么在分配之后尝试分配head.next
时会出现错误,因为无法设置null
的属性。
JavaScript正在逐个销毁数组。版本2会给你一个错误,因为JavaScript会这样做:
// What you see:
[previous, head, head.next] = [head, head.next, previous]
// What the compiler sees:
previous = head;
head = head.next; // What is head.next? It hasn't been defined! throw TypeError
head.next = previous; // [JavaScript never gets here since there was an error]
因此,为什么只有第一种解决方案有效。