【问题标题】:Javascript confusion over variables defined by reference vs valueJavascript对引用与值定义的变量的混淆
【发布时间】:2012-03-17 10:22:53
【问题描述】:

我了解 javascript 语言的以下属性:

var bar = 1;
var foo = bar;
bar = "something entirely different";
// foo is still 1

但是,当尝试将此逻辑应用于对象时,它的行为似乎有所不同:

var bar = {};
bar.prop = 1;
var foo = bar;
bar.prop = "something entirely different";
// foo.prop now changes to "something entirely different"
// but...
bar = "no longer an object";
// now foo remains an object with the prop property

谁能告诉我发生了什么以及为什么会有不同?

【问题讨论】:

  • 我可能已经回答了我自己的问题:“Javascript 总是按值传递,但是当变量引用对象(包括数组)时,“值”就是对对象的引用。”但这仍然令人困惑,有人可以解释更多吗?
  • 看看我的回答杰夫,如果这有意义,请告诉我?
  • Is Java pass by reference? 的可能重复项
  • 该问题是相关的,因为您的问题与 JavaScript 无关。
  • @MikeSamuel 你不能在Java中执行上面的代码sn-ps,你会得到一个错误。我会说使用 JavaScript 代码来参考让他感到困惑的东西会使这个关于 JavaScript 的问题。

标签: javascript variables pass-by-reference


【解决方案1】:

没错。当您将变量分配给对象时,您实际上是在创建对该对象的第二个引用。在第一种情况下,您所做的是分配bar 指向字符串foo 指向,但是当您重新分配bar 时,您更改bar 指向的内容。

在第二个示例中,将bar 分配给一个新对象,然后将foo 指向同一个对象,然后将bar 重新分配给一个字符串。 foo 仍然指向同一个对象。

可以这样想:bar = "something" 正在更改 bar 指向的内容,而不是将实际对象 {} 更改为字符串。

This article 很好地解释了您所看到的内容。不过,我正在寻找更好/更权威的参考资料。

【讨论】:

  • 这就是我要说的,包含对象bar被分配到的内存不会被删除并替换为"no longer an object"但是引用被删除(如果它没有其他引用它将排队等待垃圾收集)。
【解决方案2】:

在第一个代码中,您将 Var bar 定义为变量。

在第二个代码中你将它定义为一个对象。

变量在内存中占有一席之地;因此,当您从 bar 定义 foo 时,它的类型将与变量相同,并将保留一个新的内存位置;当您使用相等运算符时,您将替换此变量的数据内容。

第二个初始化示例代码中的对象将(作为指针)指向包含该对象数据的内存位置;当您从 bar 定义 foo 时,它的类型将与 object 相同,并将指向相同的内存位置;因此更改这两个参考对象值之一将反映另一个。

【讨论】:

    【解决方案3】:

    让我们逐行看:

    var foo = bar;
    

    对象名称所做的只是将地址保存在内存中。因此,在此语句中,您使foobar 拥有相同的内存地址。例如,如果 bar 持有 0xFF,那么通过分配,您将使 foo 也持有 0xFF。

    但是,请记住,barfoo 是两个不同的对象,它们恰好在内存中保存相同的地址。

    现在,由于它们碰巧在内存中拥有相同的地址,bar 的成员的变异也会影响foo 的成员,因为它们绑定到同一个对象。

    bar.prop = "something entirely different";  // affects foo.prop also
    

    但是,这里有一个要记住的关键点:

    Assignment only changes what the name of the object is bound to, and does not affect any other objects.

    换句话说,下面的语句使bar持有不同的内存地址,但这并不影响foo

    bar = "no longer an object"; // Made bar hold a different memory address
    

    现在,解释一下引用:

    Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.

    举个例子:

    function f(obj1, obj2)
    {
        obj1.prop = 10;
        obj2 = {prop: 20};
    }
    
    var bar = {prop: 1};
    var foo = {prop: 2};
    f(bar, foo);
    console.log("bar.prop: " + bar.prop + ", foo.prop: " + foo.prop);
    

    打印输出:bar.prop: 10, foo.prop: 2。在函数f 内部,obj1 与bar 拥有相同的内存地址,obj2 与foo 拥有相同的内存地址。但是,只有 bar 受到影响,因为在 f 内部,只反映对象的更改成员,而赋值 obj2 = {prop: 20}; 只影响局部变量 obj2 而不是 foo

    换句话说,the "value" is a reference to an object 的意思是,更改成员会影响 引用 对象,但分配只会影响局部变量。

    【讨论】:

    • 我认为这是我见过的最令人困惑的解释。忘记所有关于内存和地址的事情,ECMA-262 指定行为,而不是实现。
    • @RobG:我认为具体而不是抽象对我来说更有意义(这是我试图做的),但感谢您的评论(我意识到这种方式可能不适合每个人)。但是,更多具体的 cmets 对我会更有利。
    猜你喜欢
    • 2018-03-29
    • 2018-05-23
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    相关资源
    最近更新 更多