【问题标题】:Why do complex types work on a reference value为什么复杂类型对引用值起作用
【发布时间】:2014-09-17 12:09:01
【问题描述】:

这是那些琐碎的小问题之一,还没有给我带来任何问题(我越想越令人惊讶)但以任何方式困扰着我,我不能似乎在其他任何地方都能找到足够的答案。

假设我有两个例子

示例 1

var foo = [1,2],
    bar = foo;

bar[0] = 9;
console.log(foo, bar);

这将输出 [9,2] [9,2]。

示例 2

var foo = [1,2],
    bar = [1,2];

bar[0] = 9;
console.log(foo, bar);

这将输出 [1,2] [9,2]。

从技术角度来看,示例 1示例 2 之间有什么区别?

在示例一中,您似乎将 bar 初始化为 foo 的值,但仅更改了 bar 的值。为什么 示例 1 中的 bar[0] = 9 也会改变存储在 foo 中的值?

另一方面,如果我想这样做。假设我在运行时无法知道 foo 的值是什么,但想将 bar 初始化为与 foo 相同的值,然后更改 bar 的值,并且只更改 bar 我该怎么做?

【问题讨论】:

标签: javascript complextype


【解决方案1】:

在示例 1 中没有发生值复制,但是您将 foo 的引用分配给变量 bar

现在它们都指向同一个对象(数组,位于相同的内存位置),因此当您更改其中一个中的数组项时,它会更改两个变量指向的相同内存位置到。

要回答底部的问题,您需要复制/克隆foo,然后将该克隆(将是一个新的对象实例)分配给bar。然后您处于示例 2 中的情况,您可以在其中独立更改它们。

【讨论】:

    【解决方案2】:

    线

    bar = foo;
    

    相当于说“bar和foo指向同一个东西”

    虽然将它们都分配给 [1,2],但它们都指向不同的元素,因此您可以修改一个而无需链接另一个。

    如果你想在不改变 foo 的情况下修改 bar,你应该使用:

    var foo = [1,2];
    var bar = foo.slice(0);
    

    【讨论】:

      【解决方案3】:

      Javascript 中的数组是引用类型。

      在示例一中,您有一个数组,其中有两个变量指向它。 如果您访问两个变量之一,您将更新底层数组。当您记录它时,它与您记录的数组相同。

      在示例二中,有两个数组,每个数组都有一个指向它的变量。当你访问一个变量时,它会访问对应的Array。

      如果你想根据前一个数组初始化一个新数组而不引用同一个数组,你需要复制变量:

      var foo = [1, 2],
          bar = [];
      
      for (var i = 0; i<foo.length;i++){
          bar.push(foo[i]);
      }
      
      // or a shortcut:
      bar = foo.slice(0);
      

      这适用于数组,也适用于 JS 中的任何对象。对于对象,这称为cloning(如果您还想复制所有子对象,则称为deep-cloning

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-28
        • 2011-05-02
        • 1970-01-01
        • 2015-12-13
        • 2017-06-09
        • 2011-09-26
        • 1970-01-01
        相关资源
        最近更新 更多