JavaScript代码技巧:什么';s是foo.x的值

JavaScript代码技巧:什么';s是foo.x的值,javascript,object,variable-assignment,Javascript,Object,Variable Assignment,我在GitHub前端面试问题集合中发现了这个问题: 问题:foo.x的价值是什么 答案是未定义 我做了一些研究,我理解这个问题是(如果我错了,请纠正我): var foo={n:1}声明一个对象foo,其属性n等于1 var bar=foo声明一个对象bar,该对象引用与foo相同的对象 foo.x=foo={n:2}对象的属性x 重要的是,foo.x引用的foo是在foo更改之前确定的 见: 让lref作为计算LeftHandSideExpression的结果 设rref为赋值表达式求值的结

我在GitHub前端面试问题集合中发现了这个问题:

问题:foo.x的价值是什么

答案是
未定义

我做了一些研究,我理解这个问题是(如果我错了,请纠正我):

  • var foo={n:1}
    声明一个对象
    foo
    ,其属性
    n
    等于1
  • var bar=foo
    声明一个对象
    bar
    ,该对象引用与
    foo
    相同的对象
  • foo.x=foo={n:2}foo.x=(foo={n:2})
  • 然后我得到
    foo.x
    等于
    undefined
    。但是,
    bar.x
    的值是对象
    {n:2}
如果
bar
foo
引用同一个对象,为什么
bar.x
foo.x
未定义的情况下获取一个值?在
foo.x=foo={n:2}中真正发生的事情

foo.x = foo = {n: 2};
确定
foo.x
引用
{n:1}
对象的属性
x
,将
{n:2}
赋值给
foo
,并将
foo
-
{n:2}
的新值赋值给
{n:1}/code>对象的属性
x

重要的是,
foo.x
引用的
foo
是在
foo
更改之前确定的

见:

  • 让lref作为计算LeftHandSideExpression的结果

  • 设rref为赋值表达式求值的结果

  • 赋值运算符从右向左关联,因此您可以得到:

    foo.x = (foo = {n: 2})
    
    左侧在右侧之前进行评估

    foo.x = foo = {n: 2};
    
    这里
    foo
    指赋值前,即执行语句前的
    {n:1}
    对象

    语句可以重新写入为
    foo.x=(foo={n:2})

    在对象术语中,上述语句可以重写为
    {n:1}.x=({n:1}={n:2})

    因为赋值只能从右向左进行。所以这里我们只需要在执行开始之前检查
    foo
    是否引用了哪个对象

    关于求解R.H.S:
    foo={n:2}
    现在
    foo
    指的是
    {n:2}

    回到留给我们的问题上:

    foo.x = foo;
    
    现在L.H.S上的
    foo.x
    仍然是
    {n:1}.x
    ,而R.H.S上的
    foo
    {n:2}

    因此,在执行此语句之后,
    {n:1}
    将变成
    {n:1,x:{n:2}
    ,而bar仍然引用它。 其中as
    foo
    现在指的是
    {n:2}

    因此执行
    foo.x
    时会给出
    未定义的
    ,因为
    foo
    中只有一个值,即
    {n:2}

    但是如果您尝试执行
    bar.x
    ,它将给出
    {n:2}
    。 或者,如果只执行
    bar
    ,结果将是

    Object {n: 1, x: Object}
    

    我想我应该加上另一个,我发现的,有助于思考这个问题的方式

    这些最后的变量赋值相当于写入
    bar.x=foo={n:2},因为这些变量只是对内存中相同内容的引用

    换句话说,
    foo
    bar
    首先都引用同一个对象,
    {n:1}
    。当您使用
    foo.x=
    时,您正在访问
    {n:1}
    ,并向其中添加
    x
    属性。这可以通过
    bar
    foo
    实现,因为它们都指向内存中的同一对象!这没什么区别

    然后,当您完成这一行时,
    foo.x=foo={n:2}
    ,您将通过对象文字语法在内存中创建另一个全新的对象,并将
    foo
    设置为指向该对象,
    {n:2}
    ,而不是现在的
    {n:1,x:{n:2}
    。但是,这并不影响将
    x
    属性添加到它时
    foo
    指向的内容

    这是相当令人困惑的,但我认为有必要考虑这样一个事实:变量只是指向内存中的位置/对象的指针,而对象文字语法并没有改变以前存在的对象(即使它们看起来很相似),而是创建了一个全新的对象


    接受答案的开头可能也会有帮助。

    需要理解的是,对象变量只是JavaScript中对象的引用,而不是对象本身

    var foo={n:1}
    ->foo指的是真实对象{n:1}
    var bar=foo
    ->bar现在也是对真实对象{n:1}的引用

    棘手的部分当然是第三行:
    foo.x=foo={n:2}

    这相当于:
    (对{n:1}的引用).x=(foo={n:2})
    ->在这一行完全求值后,foo成为对新对象{n:2}的引用;但是,由于foo在求值该行之前引用原始对象
    {n:1}
    ,原始对象
    {n:1}
    变成
    {n:1,x:[引用]{n:2}
    行求值后,修改后的对象将通过参考
    访问。如果没有参考栏,原始对象将被销毁

    ,正如我所理解的表达式:

    foo.x = foo = {n: 2};
    
    完全一样:

    foo.x = {n: 2} ; 
    foo = {n: 2};
    
    在这之后,很明显:

     bar=={n: 1, x: {n:2}};
     foo=={n:2};
     foo.x==undefined
    

    我认为在Javascript中,如果对象不是空的,就不能为不存在的属性赋值。因此,在本例中,foo对象有一个属性和值对,即{n:1}因此,因为它不是空的,它没有X属性,所以不能赋值,但是因为您将条形码对象指定为FO对象的值,所以无论FoO是

    它都将具有值,而在面试中这样的问题是可怕的……我会认为这是一个错误。
     bar=={n: 1, x: {n:2}};
     foo=={n:2};
     foo.x==undefined