【问题标题】:Why does reference = null not affect the referenced object?为什么reference = null 不影响被引用的对象?
【发布时间】:2012-08-03 23:19:03
【问题描述】:

我知道这行得通,但我不知道为什么或为什么它会以这种方式工作:

var foo = [5, 10];
var bar = foo;
console.log(foo); //[5, 10]
console.log(bar); //[5, 10]
bar[0] = 1; 
console.log(foo); //[1, 10]
bar = null;
console.log(foo); //[1, 10]

我不仅希望bar 变为空,而且还希望foo 变为空。我希望得到一些帮助来理解这一点。

【问题讨论】:

  • 你为什么会这样?
  • 因为bar 是对对象的引用(“指针”),而不是实际的对象本身。
  • 但是就像我演示的那样,指向对象属性的指针会影响值本身,这就是我的困惑所在。
  • @Bloodyaugust:你应该看看rebinding and mutating 操作之间的区别。 bar[0] = 1 正在变异;它会影响bar 指向的对象。 bar = None 正在重新绑定;它只会影响标识符 bar 的含义。
  • @DavidRobinson:你为什么不把它放在一个答案中?它回答了我问题的第一部分,谢谢!

标签: javascript types reference null


【解决方案1】:

当您执行bar = null; 时,它只是为bar 变量的值赋值。它不会影响过去分配给bar 的内容。该对象继续存在,如果有其他引用它,它仍然存在,其价值不受影响。

当你这样做时:

var foo = [5, 10];
var bar = foo;

你有三个实体。您有一个数组 [5,10] 和两个变量,每个变量都引用了该数组。如果更改数组,则由于两个变量都指向同一个数组,因此无论您通过哪个变量引用数组,都会看到更改。

但是,如果您设置bar = null,那只会影响bar 变量,该变量将不再具有对数组的引用。它根本不影响foo 仍然指向的数组。

事实上,如果你这样做了:

var foo = [5, 10];
var bar = foo;
bar = [20,30];

你会得到同样的结果。在第二行代码之后barfoo 都指向同一个数组,但是在第三行之后,bar 现在指向一个新数组,而只有foo 指向原始数组。关键是要意识到使用bar 修改它指向的对象(如bar[0] = 1)与重新分配bar 的整个值(如bar = [20,30])是有区别的。在第一种情况下,foobar 指向的基础对象已更改。在第二种情况下,bar 最初指向的底层对象没有被触及。相反,bar 被更改为指向一个新对象,并且之前的对象没有被触及。

【讨论】:

    【解决方案2】:

    区别在于rebinding and mutating 操作。

    bar[0] = 1
    

    正在变异;它会影响bar 指向的对象。

    bar = null
    

    正在重新绑定;它只会影响标识符 bar 的含义。

    【讨论】:

    • 太好了,这就是我要找的!但是语言以这种方式工作的原因是什么?对我来说,突变和重新绑定是一回事。
    • @Bloodyaugust:如果语言不能以这种方式工作(如果没有重新绑定操作),想象一下for 在列表上的循环将如何工作。 for 循环的每次迭代都可能有类似x = lst[i] 的行,这将改变变量x 所包含的内容,因此之前分配给x 的每个变量!
    • 因为没有引用(绑定),您将不得不传递整个数组,而不仅仅是指向它的指针。
    • 另外,为什么 bar = null 被认为是重新绑定而不是突变?
    • bar = null 是重新绑定。更具体地说,是“解除绑定”。
    【解决方案3】:

    你有两个指向数组的指针。 Bar = foo 复制原始指针。取消引用 bar 不会取消引用 foo。

    阅读更多@ http://snook.ca/archives/javascript/javascript_pass

    【讨论】:

      【解决方案4】:

      当你这样做时

      var foo = [5, 10];
      

      它创建一个对数组的引用,像这样

      foo --->  [5, 10]
      

      当您将bar 分配给foo 时,您现在拥有

      foo --->  [5, 10]
      
      bar ------^
      

      当你打电话时

      bar[0] = 1;
      

      你得到

      foo --->  [1, 10]
      
      bar ------^
      

      其中foobar 指向同一个对象。

      当你打电话时

      bar = null;
      

      你现在有

      foo --->  [1, 10]
      

      【讨论】:

        【解决方案5】:

        引用,但它的定义只是指向某个对象的指针。当您将null 分配给bar 时,您只需删除存储在bar 中的这个“指针”,使其不再指向对象。

        把它想象成一个写在纸上的地址。如果工作表foobar 上有相同的地址,然后您发出命令:转到写在工作表foo 上的地址,然后在里面放一些东西,在操作完成后,自然,无论谁查看这些工作表中的任何一个并检查该地址,会发现这些变化。现在你对null 的分配就像用橡皮擦从工作表上擦除这个地址一样。它既不会触及任何其他床单,也不会以任何方式触及房屋。

        【讨论】:

          【解决方案6】:

          我喜欢将变量视为标签。让他们更容易解释。

          //Create an array containing 5 and 10, and put the label "foo" on it
          var foo = [5, 10];
          //Put the label "bar" on the thing with the label "foo"
          var bar = foo;      
          console.log(foo); //[5, 10]
          console.log(bar); //[5, 10]
          //Take the thing labeled "bar" (which also has the label "foo") and change the first element to 1
          bar[0] = 1;         
          console.log(foo); //[1, 10]
          //Take the label "bar" and attach it to nothing
          bar = null;
          console.log(foo); //[1, 10]
          

          var foo = [5, 10]; var bar = foo; 控制台.log(foo); //[5, 10] 控制台.log(栏); //[5, 10] 条[0] = 1; 控制台.log(foo); //[1, 10] 酒吧=空; 控制台.log(foo); //[1, 10]

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-01-14
            • 1970-01-01
            • 1970-01-01
            • 2019-07-09
            相关资源
            最近更新 更多