我在反转链表时遇到了一些奇怪的解构行为这个问题:
/**
* 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 不工作的方式吗?
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]
因此只有第一个解决方案有效。
如果将解构分解为单独的任务,则更容易看出差异。
版本 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.next
之后分配 head = head.next
。但是您需要更改原始next
节点的head
属性,而不是新节点。
如果原来的
head.next
是null
,赋值后尝试赋值head.next
会报错,因为不能设置null
的属性。