Javascript 为什么foo.x=foo={n:2}中没有定义foo.x的值?
此代码:Javascript 为什么foo.x=foo={n:2}中没有定义foo.x的值?,javascript,Javascript,此代码: var foo = {n: 1}; var bar = foo; foo.x = foo = {n: 2}; 你能解释一下什么是: foo.x = foo = {n: 2}; 我看到{n:2}被分配给foo。为什么未定义分配给foo.x?Doesfoo={n:2}返回未定义?,因为左侧的属性访问foo.x在右侧之前进行评估 让我们通过为正在计算的临时表达式指定新名称,更清楚地了解代码的实际功能: var foo0 = {n: 1}; var foo1 = {n: 2}; foo0.
var foo = {n: 1};
var bar = foo;
foo.x = foo = {n: 2};
你能解释一下什么是:
foo.x = foo = {n: 2};
我看到
{n:2}
被分配给foo
。为什么未定义分配给foo.x
?Doesfoo={n:2}代码>返回未定义
?,因为左侧的属性访问foo.x
在右侧之前进行评估
让我们通过为正在计算的临时表达式指定新名称,更清楚地了解代码的实际功能:
var foo0 = {n: 1};
var foo1 = {n: 2};
foo0.x = foo1;
foo0 = foo1;
console.log(foo0.x);
因此foo0.x
是foo1.x
是未定义的
在原始代码中,您可以看到bar.x
是{n:2}
,确认了这一解释。因为您将foo分配给了一个具有单个属性的对象,{n:2}
在JavaScript中,表达式从右向左求值。因此,当您尝试访问foo.x
时,您正试图从新分配的foo值{n:2}
中获取x
的值,根据JavaScript规范,这是未定义的,左侧总是首先求值:
12.14.4运行时语义:评估
AssignmentExpression[In,Yield]:LeftHandSideExpression[?Yield]=AssignmentExpression[?In,Yield]
如果LeftHandSideExpression既不是ObjectLiteral也不是ArrayLiteral,则
1.让lref作为计算LeftHandSideExpression的结果
如果向foo
对象添加另一个引用,则可以清楚地看到:
var ref = {n:1};
var foo = ref;
var bar = foo;
foo.x = foo = {n: 2};
ref.x
之所以存在,是因为foo.x
引用了foo
的未修改值,赋值表达式的左侧将首先求值,即使运算符具有从右到左的优先级。因此,表达式foo.x=foo={n:2}
与foo.x=(foo={n:2})
的计算方式相同:
计算左侧表达式foo.x
以获得引用,右侧表达式的值将被分配到该引用。
对右侧表达式求值,以获取将要指定的值。右侧是另一个赋值表达式,因此其求值方式相同:
评估foo
以确定分配到的位置
计算创建对象的表达式{n:2}
,以确定要分配的值
将{n:2}
分配给foo,并返回{n:2}
将右侧表达式求值的值({n:2}
)分配给在步骤1中解析为foo.x
的引用(之前foo
分配了新值)。这也与bar.x
相同,因为前面一行上有赋值bar=foo
完成此操作后,bar
仍作为引用的原始对象将具有一个x
属性,该属性引用创建的第二个对象foo
也是对第二个对象的引用,所以foo===bar.x
为什么要进行向下投票?这是一个有趣的问题。@Juhana你介意修复你的编辑吗?@djechlin有什么问题吗?@Juhana你恢复了格式和语言的改进。@djechlin我看不出“这段代码”是如何改进的,但是YMMV。那么“foo.x=”。。。do?@djechlin它被分配给foo,但是foo被重写为一个没有x值的对象我现在知道这是正确的,但这并不奇怪,它让人困惑。看起来我们有一个赢家。foo.x=(foo={n:2})
甚至有意义吗,我刚刚在chrome上测试过,它也有同样的功能results@johnny5如果foo
不是一个对象,那就没有意义了,但从第一句话开始,它就是一个对象。完整重复问题链接的最佳答案。@Paulpro是foo.x=foo={n:2};分解为foo.x={n:2};foo={n:2}?