a.x=a={n:b}在JavaScript中是如何工作的?
这是有关的 我明白a.x=a={n:b}在JavaScript中是如何工作的?,javascript,Javascript,这是有关的 我明白 foo = foo.x = {n: b}; // console.log(foo) => {n: b} 但是 它应等于: foo = {n: b}; foo.x = foo; // console.log(foo) => {n: b, x:object} 我在这里遗漏了什么吗?它等于 let tmp = foo; foo = {n: b}; tmp.x = foo; 您可以看到,旧的foo(在本例中存储在z中)已被修改: > z=foo={}; {}
foo = foo.x = {n: b}; // console.log(foo) => {n: b}
但是
它应等于:
foo = {n: b};
foo.x = foo; // console.log(foo) => {n: b, x:object}
我在这里遗漏了什么吗?它等于
let tmp = foo;
foo = {n: b};
tmp.x = foo;
您可以看到,旧的foo
(在本例中存储在z
中)已被修改:
> z=foo={};
{}
> foo.x = foo = {n: b};
{ n: 10 }
> foo
{ n: 10 }
> z
{ x: { n: 10 } }
我明白了
var foo = {}; // now foo is a reference point to object {}
foo.x = foo = {n:1}; // first foo is refer to a new object {n:1}, then old foo referred object {} set a prop x
// try this to get what you want
var foo = foo1 = {};
foo.x = foo = {n:1};
console.log(foo, foo1) // here foo1 is what you want
与:
在继续实际分配之前,首先对前面的foo.x
进行部分评估,足以确定分配的确切目标
它的行为更符合以下几点:
var oldFoo = foo;
foo = {n: b};
oldFoo.x = foo;
。
=
的左侧在将值放入(1.f)之前进行计算(1.a):
AssignmentExpression:LeftHandSideExpression=AssignmentExpression
1) 如果LeftHandSideExpression既不是ObjectLiteral也不是ArrayLiteral,则a) 让lref作为计算LeftHandSideExpression的结果。
…
f) 表演?PutValue(lref,rval)
这是因为当你写作的时候
var foo = {};
foo.x = foo = {n: b} //a=b=c
当执行该行时,foo指向{}
,但当该语句分解为
foo.x = (foo = {n: b}) /a=(b=c)
foo的引用已从{}
更改为{n:b}
,但foo.x
(a)中的foo
(a)仍然指向foo
的旧引用,因为左手表达式是在作业开始之前评估的
按照
foo.x
仍然引用旧的foo
所以,如果你通过这样做稍微调整一下你的例子
var foo = {z:2};
foo.x = foo.n = {n: 1};
在本例中,您没有将引用更改为foo
,只指定了新属性,因此现在输出为
对象{z:2,n:Object,x:Object}
现在,它保留了对旧的
foo
的引用,因为没有分配新的引用,因此所有属性z
,n
和x
都被保留。console.log(foo.x)应该打印出相同的内容。我遇到一个错误“无法设置未定义的属性“x”除非foo
已经引用了某个对象,否则我看不出第一行如何工作。(第二个也是如此,尽管直觉上第二个“感觉”它应该按原样工作。)你说它应该等于什么,没有任何理由。没有理由,因为这句话是假的。你能给我解释一下你为什么相信这个谎言吗?这有助于我理解为什么人们相信编程语言是错误的。其他答案描述了这就是正在发生的事情,但是一个tmp
和foo
的例子一开始就有了与它们的值相同的对象,这就更清楚了。
foo.x = (foo = {n: b}) /a=(b=c)
var foo = {z:2};
foo.x = foo.n = {n: 1};