javascript 为什么在给它分配其他东西时不通过引用传递这个对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9437981/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 06:41:07  来源:igfitidea点击:

Why isn't this object being passed by reference when assigning something else to it?

javascriptpass-by-reference

提问by Dev555

I know that in JS, objects are passed by reference, for example:

我知道在JS中,对象是通过引用传递的,例如:

function test(obj) {
    obj.name = 'new name';
}

var my_obj = { name: 'foo' };
test(my_obj);
alert(my_obj.name); // new name

But why doesn't the below work:

但为什么以下不起作用:

function test(obj) {
    obj = {};
}

var my_obj = { name: 'foo' };
test(my_obj);
alert(my_obj.name); // foo

I have set the object to {}(empty) but it still says foo.

我已将对象设置为{}(空),但它仍然显示foo.

Can any one explain the logic behind this?

任何人都可以解释这背后的逻辑吗?

回答by Alexander Varwijk

If you are familiar with pointers, that's an analogy you can take. You're actually passing a pointer, so obj.somePropertywould dereference to that property and actually override that, while merely overriding objwould kill off the pointer and not overwrite the object.

如果您熟悉指针,那么您可以进行类比。您实际上是在传递一个指针,因此obj.someProperty会取消对该属性的引用并实际覆盖它,而仅覆盖obj会杀死指针而不覆盖对象。

回答by Adam Rackis

Because JavaScript actually passes objects by pass-by-copy-reference.

因为 JavaScript 实际上是通过 pass-by- copy- reference 来传递对象的。

When you pass my_objinto your testfunction, a copyof a reference to that object is passed in. As a result, when you re-assign the object in test, you're really only re-assigning a copy ofa reference to the original object; your original my_objremains un-changed.

当您传入my_obj您的test函数时,会传入对该对象的引用副本。因此,当您在 中重新分配对象时test,实际上只是重新分配了对原始对象的引用副本;您的原始文件my_obj保持不变。

回答by Quentin

Because you are overwriting the reference, not the object.

因为您正在覆盖引用,而不是对象。

// Create a new object and assign a reference to it
// to the variable my_obj
var my_obj = { name: 'foo' };

// Pass the reference to the test function
test(my_obj);

// Assign the reference to a variable called obj
// (since that is the first argument)
function test(obj) {
// Create a new (empty) object and assign a reference to it to obj
// This replaces the existing REFERENCE
    obj = {};
}
// my_obj still has a reference to the original object, 
// because my_obj wasn't overwritten
alert(my_obj.name); // foo

回答by Timo K?hk?nen

Javascript lacks support for passing by reference (although objects are passed by reference and the reference is maintained as long as it is not overwrited with assignment eg. using =), but you can imitate refkeyword of C# using the following technique:

Javascript 不支持通过引用传递(尽管对象是通过引用传递的,并且只要没有被赋值覆盖,引用就会被维护,例如 using =),但是您可以ref使用以下技术模仿C# 的关键字:

function test(obj) {
  obj.Value = {};
  //obj.Value = {name:"changed"};
}

var my_obj = { name: 'foo' };

(function ()
{
  my_obj = {Value: my_obj};
  var $return = test(my_obj);
  my_obj = my_obj.Value;
  return $return;
}).call(this);

alert(my_obj.name); // undefined, as expected
                    // In the question this returns "foo" because
                    // assignment causes dereference

Of course you can use globals and call function without arguments, in which case the references are not missed like this:

当然,您可以使用不带参数的全局变量和调用函数,在这种情况下,不会像这样错过引用:

var obj = { name: 'foo' };
function test() {
    obj = {};
}
test();
alert(obj.name); // undefined

If you have all your code in closure, then things are simpler and above like globals doesn't pollute global namespace:

如果你的所有代码都在闭包中,那么事情就更简单了,就像 globals 不会污染全局命名空间一样:

(function(){
    var obj = { name: 'foo' };
    function test() {
        obj = {};
    }
    test();
    alert(obj.name); // undefined
}).call(this);

The above "globals inside closure" -technique is nice if you have to port to Javascript some C# code which has refarguments. Eg. The following C# code:

如果您必须将一些带有ref参数的C# 代码移植到 Javascript,上面的“闭包内的全局变量”技术非常有用。例如。以下 C# 代码:

void MainLoop()
{
   // ...
   MyStruct pt1 = CreateMyStruct(1);
   MyStruct pt2 = CreateMyStruct(2);
   SwapPoints(ref pt1, ref pt2);
   // ...
}
void SwapPoints(ref MyStruct pt1, ref MyStruct pt2)
{
    MyStruct tmp = pt1;
    pt1 = pt2;
    pt2 = tmp;
}

could be ported to Javascript using something like:

可以使用以下内容移植到 Javascript:

(function(){
    var pt1, pt2;
    function CreateMyStruct(myvar)
    {
      return {"myvar":myvar}  
    }
    function MainLoop()
    {
       // ...
       pt1 = CreateMyStruct(1);
       pt2 = CreateMyStruct(2);
       console.log("ORIG:",pt1,pt2); 
       SwapPoints(); 
       console.log("SWAPPED:",pt1,pt2);
       // ...
    }
    function SwapPoints()
    {
        var tmp = pt1;
        pt1 = pt2;
        pt2 = tmp;
    }
    MainLoop();

}).call(this);

or if it's essential to use local variables and function arguments, then solution can be based on the first example of my answer like this:

或者如果必须使用局部变量和函数参数,那么解决方案可以基于我的答案的第一个示例,如下所示:

(function(){
    function CreateMyStruct(myvar)
    {
      return {"myvar":myvar}  
    }
    function MainLoop()
    {
      // ...
      var pt1 = CreateMyStruct(1);
      var pt2 = CreateMyStruct(2);
      console.log("ORIG:",pt1,pt2); 

      (function ()
      {
        pt1 = {Value: pt1};
        pt2 = {Value: pt2};
        var $return = SwapPoints(pt1, pt2);
        pt1 = pt1.Value;
        pt2 = pt2.Value;
        return $return;
      }).call(this);

      console.log("SWAPPED:",pt1,pt2);
      // ...
    }
    function SwapPoints(pt1, pt2)
    {
      var tmp = pt1.Value;
      pt1.Value = pt2.Value;
      pt2.Value = tmp;
    }
    MainLoop();
}).call(this);

Really have to say that Javascript lacks much when it has not native ref! The code would be much simpler.

真的不得不说,当它不是原生的时候,Javascript 缺乏很多ref!代码会简单得多。