【问题标题】:Pass-by-reference JavaScript objects引用传递 JavaScript 对象
【发布时间】:2016-09-14 10:00:18
【问题描述】:

请阅读下面代码中的 cmets 以了解我在尝试什么 问。

预期输出:根据 JavaScript 中的传递引用机制,objOne 预计最后会记录 {},因为 objTwo 是用 {} 初始化的。

var objOne = {
  x: 1,
  y: 2
};

var objTwo = objOne;

// change the x vlaue to 2 by objTwo
objTwo.x = 2;

// Change the value of key x in objOne as well - pass by reference mechanism
console.log(objOne); // { x: 2, y: 2 }

/*** Pass by reference is understood in code, above this comment ***/

// Now what if objTwo initialized with empty object
objTwo = {};

console.log(objOne); // { x: 2, y: 2 } but expected output = {}

// As per pass by reference mechanism. objOne is expected to log {}, because objTwo was initialized with {}.

【问题讨论】:

  • 在案例 1 中,objOneobjTwo 都指向同一个对象。所以可以通过其中任何一个更改x。重新初始化 objTwo 意味着你让它不再引用同一个对象。这不会导致所有其他现有引用变为 {}
  • 按引用的是 object,而不是变量。
  • 当你做 objTwo = {};发生的事情是我将引用更改为空对象。
  • JavaScript 根本没有“按引用传递”,句号。 JavaScript 是一种纯粹的按值传递语言。引用传递在计算机编程中具有特定的含义:它将对变量的引用传递给函数。 JavaScript 从不这样做。

标签: javascript


【解决方案1】:

当您将一个变量分配给另一个变量时,并不是这两个变量现在都通过引用链接了;您误解了“通过​​引用传递”的含义。

持有对象的变量并不“直接”持有对象。它所持有的是对对象的引用。当您将该引用从一个变量分配给另一个变量时,您正在制作该引用的副本。现在两个变量都持有一个对象的引用。通过该引用修改对象会更改持有对该对象的引用的两个变量。

当您为其中一个变量分配新值时,您只是在修改该变量所包含的值。该变量现在不再持有对该对象的引用,而是持有其他东西。另一个变量仍然保持对原始对象的引用,赋值根本没有影响它。

【讨论】:

  • “你误解了这里的“通过引用”是什么意思” 我想借此机会告诉他们 JavaScript 没有通过引用完全没有
  • @jpmc26 不。如果您分配的不是对象,将不再有“引用”。变量保存的值是引用,但变量也可以保存其他值。
  • @Caleth:这纯粹是按值传递。是的,该值可以是对象引用。对象引用就像其他任何值一样。
  • 是的,使用该值可以为您提供对象上的引用语义,这是人们说“通过引用传递”时所关心的
  • @Caleth:(如果您不@ 不是作者的人,他们将不会收到您的评论通知。)这不是传递引用的意思,所以如果你遇到那些人,向他们解释。 :-) 引用传递是计算机科学界的一个艺术术语。它是指将对变量的引用传递给函数。 JavaScript 不这样做。对于 JavaScript 等语言中的对象引用,最重要的理解之一是它们只是值
【解决方案2】:

当你评估时

objTwo = {};

Javascript 将其解释为将 objTwo 重新分配给一个新的文字空对象,并保留其旧值。

如果你想通过引用从 objOne 中删除一个键,你可以使用 delete 关键字:

delete objTwo.x;  // also deletes the x property of objOne

【讨论】:

    【解决方案3】:

    当 2 个变量指向同一个对象时,这并不意味着它们现在神奇地“绑定”到彼此。

    在您的情况下,objTwo = {} 只是将 objTwo 更改为指向您创建的新对象。

    【讨论】:

      【解决方案4】:

      objTwo = {}; 无法按照您认为的方式工作。我通常建议将变量视为“指针”。

      objOneobjTwo 是两个完全不同的变量。当您执行objTwo = {}; 时,它所做的就是让objTwo 变量指向另一个对象。它不会改变 objOne 变量。

      让我们想象一下:

      var objOne = {
        x: 1,
        y: 2
      };
      
      // objOne -> { x: 1, y: 2 }
      
      var objTwo = objOne;
      
      // objOne -> { x: 1, y: 2 } <- objTwo
      
      objTwo.x = 2;
      
      // objOne -> { x: 2, y: 2 } <- objTwo (update object via objTwo variable)
      
      objTwo = {};
      
      // objOne -> { x: 2, y: 2 }, objTwo -> {}
      

      【讨论】:

        【解决方案5】:

        我同意接受的答案,这只是一些支持它的代码。

        let objOne = {x: 1, y: 2};
        let objTwo = objOne; // referencing to same thing
        
        objTwo.x = 2;
        console.log(objOne, objTwo); // output {x:2, y:2}, {x:2, y:2}
        
        let objThree = {};
        objTwo = objThree; // notice this. Same as "objTwo = {}", except now you have objThree as initial reference
        console.log(objOne, objTwo, objThree); // output {x:2, y:2}, {}, {}
        
        

        您可以通过更改 objTwo 引用或添加完整的新值来轻松注意到发生了什么,如问题示例中所示。

        【讨论】:

          【解决方案6】:

          只有删除才能调用初始化状态..

          for(var i in objOne){
              delete objOne[i];
          }
          

          @nrabinowitz 说

          • Javascript 总是按值传递,但是当变量引用对象(包括数组)时,“值”是对对象的引用。
          • 更改变量的值不会改变底层基元或对象,它只是将变量指向一个新的基元或对象。
          • 但是,更改由变量引用的对象的属性确实会更改底层对象。

          【讨论】:

            【解决方案7】:

            JavaScript 通过引用传递是不同的,只要您更改对象的属性(如 obj.x = 1),您的对象就会被视为引用,但对象变量本身的赋值(obj = [])会将其视为基于值的变量。

            【讨论】:

            • 赋值不会改变对象,它会改变变量obj
            【解决方案8】:

            这就是传递引用的工作方式。这里 objTwo 指的是 objOne,所以无论你对 objTwo 做什么,objOne 也会发生。

            【讨论】:

              猜你喜欢
              • 2012-07-16
              • 2015-09-19
              • 1970-01-01
              • 2019-06-05
              • 2015-06-18
              • 2015-03-06
              • 2012-01-26
              • 2016-09-27
              • 1970-01-01
              相关资源
              最近更新 更多