重新理解连续赋值

420 阅读1分钟

以前我以为:

var x = y = 100

就是连续赋值。

实际上,上边的语句中, var x 只是声明一个 x ,然后用 y = 100 的结果值去初始化 x 。

那什么是连续赋值呢?举个🌰:

var a = {n:1},
// 这才是连续赋值
a.x = a = {n:2};

但是:

console.log(a.x); // --> undefined

为什么呢?

原因是:a 被重新赋值为 {n:2} 后, a 的引用变成了全新的,而 js 遵循从左向右的执行原则,a.x 拿到的是老的 a 的属性引用,console.log(a.x) 中的 a 是新的 a ,所以 undefined 。

如何证明:

var a = {n:1}, ref = a; // ref暂存了“原始的a”
a.x = a = {n:2};

console.log(a.x); // undefined
console.log(ref.x); // object {n:2}
console.log(ref.n); // 1 

于是我们可以利用连续赋值实现一个链表:

var i = 10, root = {index: "NONE"}, node = root;// 创建链表
while (i > 0) {
  node.next = node = new Object; node.index = i--; // 这里可以开始给新node添加成员
  node.name = `name ${i + 1}`
}
// 测试
node = root;
while (node = node.next) { console.log(node);}

补充:关于 . 运算:

如果点运算在后续运算中被作为 lhs,例如 node.next = ...,那么它就是作为“引用”来使用,这样就可以访问到x这个属性,并置值;如果它在后续运算中被作为 rhs,例如 console.log(node.next),那么它就会被 GetValue() 取值(并作为值来使用)。

点运算整体被作为“一个操作数”,它的用法与它被使用的位置是有关的。但是“得到它(亦即是对a.x这个表达式求 Result )”的过程并没有什么不同。