为什么在向该对象分配其他内容时不通过引用传递该对象?

发布于 2025-01-08 13:46:32 字数 427 浏览 0 评论 0原文

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

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

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

但是为什么下面的不起作用:

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

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

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

谁能解释一下这背后的逻辑吗?

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

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.

Can any one explain the logic behind this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

戴着白色围巾的女孩 2025-01-15 13:46:32

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

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

眼睛会笑 2025-01-15 13:46:32

因为 JavaScript 实际上是通过复制引用传递对象的。

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

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

When you pass my_obj into your test function, a copy of 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 of a reference to the original object; your original my_obj remains un-changed.

十年九夏 2025-01-15 13:46:32

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

// 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

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
很糊涂小朋友 2025-01-15 13:46:32

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

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

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

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

如果您将所有代码都放在闭包中,那么事情会更简单,就像上面这样globals 不会污染全局命名空间:

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

如果您必须将一些带有 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;
}

可以使用类似以下内容移植到 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);

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

(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);

真的不得不说 Javascript 缺乏很多它没有本机ref!代码会简单得多。

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 ref keyword of C# using the following technique:

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:

(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 ref arguments. Eg. The following C# code:

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:

(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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文