破坏错误取决于变量的顺序



在这个问题中反转链表时,我遇到了一些奇怪的析构函数行为:

/**
* 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.nextnull,那么在分配之后尝试分配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]

因此,为什么只有第一种解决方案有效。

最新更新