【问题标题】:Javascript's assignment operation is to copy references?Javascript的赋值操作是复制引用?
【发布时间】:2012-02-06 05:20:53
【问题描述】:

基本示例:

var b = 10;
var c = b;
b++;
console.log(b,c);

>> 11 10

c 看起来像 b 的副本。

但在另一种情况下:

var x = {};
var y = x;
x.abc = 10;
console.log(x.abc, y.abc);

>> 10 10

为什么y 不是x 的副本,而是指向同一个实例x 指向的引用?

另外,我猜b++ 创建了另一个实例,所以b 指向新实例,而c 指向旧实例。不过……

var u = 10;
setTimeout(function() {
  console.log(u);
}, 10000)
u++;

>> 11

如果u++ 创建了一个新实例,那么匿名函数内部的u 应该指向旧的u,不是吗?

【问题讨论】:

    标签: javascript reference variable-assignment


    【解决方案1】:

    当基元被赋值时,它们被按值赋值;引用类型(如您的对象)通过引用分配(或者,正如 Jon Skeet 纠正我的那样,它们被分配了引用的副本)。

    在您的第二个示例中,x 和 y 都 指向内存中的同一个对象。这就是为什么将abc 属性添加到一个,也会将其添加到另一个

    您还会观察到将 x 或 y 传递给函数的相同行为

    function addABC(foo) {
       foo.abc = 10;
    }
    
    var x = {};
    var y = x;
    addABC(x);
    console.log(x.abc, y.abc);
    

    请注意,虽然 x 和 y 指向内存中的同一个对象,但它们是引用的单独副本,所以这个

        var x = { a: 1 };
        var y = x;
        y = {};
        alert(x.a);
    

    还有这个

        var x = { a: 1 };
        var y = x;
        x = {};
        alert(y.a);
    

    仍会提醒 1。

    【讨论】:

    • 我不喜欢这里的“通过引用”的术语 - 因为 真正的“按引用传递”或“按引用复制”有些不同。例如,假设您更改了addABC 方法改成foo = "hello",这不会改变x 的值,对吗?(诚然,我*假设 JavaScript 在这里的工作方式与Java 和C# 相同,但我认为这是一个合理的假设。)
    【解决方案2】:

    此声明:

    var y = x;
    

    复制x 的值作为y 的初始值。但是,所涉及的值是对象的引用,而不是对象本身。请注意,这与说分配复制“对x 的引用”相同 - 它实际上是x。因此,特别是,如果您更改 x 的值以引用不同的对象,例如

    x = "something else";
    

    那么这不会改变 y 的值 - 它的值仍然是对原始对象的引用。

    【讨论】:

    • 乔恩斯基特?!?!在 JavaScript 标记中?!?!欢迎您,好先生!
    • @AdamRackis:他以前曾在这个池塘里泡过脚。
    【解决方案3】:

    c 看起来像 b 的副本。

    两者都是对同一个不可变值的引用。

    为什么y 不是x 的副本,而是指向x 指向的实例的引用?

    x 首先是对对象的引用,所以y 是它的副本(引用的副本,而不是对象的副本)。

    如果u++ 创建一个新实例,

    没有。

    匿名函数中的u 应该指向旧的u,不是吗?

    u++ 将对 11 的引用分配给 u。匿名函数查看的是u,而不是“创建函数时u 的值”。

    【讨论】:

    • @Quentin:所以原始“对象”只是驻留在由 js 实现(ES3/5)创建的“激活对象”或“词法环境”中的某个位置,并且永远不会真正被 ECMAscript 触及本身。
    • "两者都是对同一个不可变值的引用。"这与观察到的输出“11 10”不矛盾吗?输出表明它们是对不同值的引用
    • @Neptilo — 不。阅读答案的下半部分。
    • @Quentin 那么你的意思是bc 是对执行b++ 之前 的相同值的引用吗?但是之后,b 变成了对另一个值的引用,对吧?
    • @Neptilo — 是的。
    【解决方案4】:
    • 分配给变量的值的类型决定了该值是按值分配还是按引用分配

    • 在变量赋值时,标量原始值(数字、字符串、布尔值、未定义、null、符号)按值赋值,复合值(对象、数组)按引用赋值

    如果有疑问,请查看此内容,并通过示例进行解释 关联: how references work

    【讨论】:

      猜你喜欢
      • 2019-10-13
      • 1970-01-01
      • 2013-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 2014-01-15
      相关资源
      最近更新 更多