反转链表中JavaScript解构赋值顺序引发执行差异的原因解析
解构赋值反转链表时的异常行为解析
在LeetCode「反转链表」问题中,以下代码只有版本1的解构赋值能正常运行,版本2、3均会抛出TypeError: Cannot set properties of null (setting 'next')错误,原因在于ES6解构赋值的执行逻辑:
/** * 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 - 正常运行 [head.next, head, previous] = [previous, head.next, head] // Version 2 - 报错 // [previous, head, head.next] = [head, head.next, previous] // Version 3 - 报错 // [head, head.next, previous] = [head.next, previous, head] } return previous };
报错信息:
Line 16 in solution.js [previous, head, head.next] = [head, head.next, previous] ^ TypeError: Cannot set properties of null (setting 'next')
核心原因:解构赋值的执行顺序
ES6解构赋值遵循先计算右侧所有值并暂存,再按左侧顺序依次赋值的规则,问题出在左侧赋值的顺序上:
版本1(有效)
[head.next, head, previous] = [previous, head.next, head]
执行步骤:
- 先把右侧三个值暂存:
temp1 = previous、temp2 = head.next、temp3 = head - 按左侧顺序赋值:
- 把
temp1赋值给head.next(此时head还是当前有效的链表节点,不是null) - 把
temp2赋值给head(此时head可能变为null,但已经完成了head.next的修改) - 把
temp3赋值给previous
整个过程中,修改head.next时head始终是有效节点,不会触发null错误。
- 把
版本2(无效)
[previous, head, head.next] = [head, head.next, previous]
执行步骤:
- 暂存右侧值:
temp1 = head、temp2 = head.next、temp3 = previous - 按顺序赋值:
- 把
temp1赋值给previous - 把
temp2赋值给head——当处理链表最后一个节点时,temp2是null,此时head变为null - 尝试把
temp3赋值给head.next,但head已经是null,null没有next属性,直接抛出错误。
- 把
版本3(无效)
[head, head.next, previous] = [head.next, previous, head]
执行步骤:
- 暂存右侧值:
temp1 = head.next、temp2 = previous、temp3 = head - 按顺序赋值:
- 把
temp1赋值给head——同样,处理最后一个节点时head会变为null - 尝试把
temp2赋值给head.next,此时head是null,触发相同的错误。
- 把
总结
版本1的关键是先修改当前节点的next指针,再更新head指向,避免了head变为null后再去访问它的next属性。而版本2、3都把head的更新放在了修改head.next之前,导致后续操作访问null的属性报错。
内容的提问来源于stack exchange,提问作者Jordan
相关产品推荐
相关产品推荐

