【问题标题】:Prototype array param [duplicate]原型数组参数
【发布时间】:2016-03-02 16:08:04
【问题描述】:

我认为我没有理解整个原型流程,我有这个问题:

function SomeO() {};
SomeO.prototype.arr = [];
SomeO.prototype.str = "";

var s1 = new SomeO();
var s2 = new SomeO();

s1.str+="1"
console.log(s2) // "" OK

s1.arr.push(1)
console.log(s2) // [1] WHY???

为什么当我将一项添加到一个对象中的数组时,它具有相同的数组实例?

【问题讨论】:

    标签: javascript arrays oop prototype instance


    【解决方案1】:

    这是因为对象通过引用被你的“SomeO”对象的所有实例共享,在这种情况下你的“arr”属性,并且像字符串或数字这样的东西是通过值共享的,所以字符串的修改不会影响其他实例的值。

    所以在这种情况下得到这个结果是正常的。

    function SomeO() {};
    SomeO.prototype.arr = [];
    SomeO.prototype.str = "chimichangas";
    
    var s1 = new SomeO();
    var s2 = new SomeO();
    
    s1.str+="1"
    console.log(s1.str); // "chimichangas1" OK because is by value
    console.log(s2.str); // "chimichangas"  OK because is by value
    
    s1.arr.push(1);
    console.log(s2.arr); // [1] WHY??? because is by reference

    如果你不想共享数组,你应该做类似的事情。

    function SomeO() {
      this.arr = [];
    };
    SomeO.prototype.str = "";
    
    var s1 = new SomeO();
    var s2 = new SomeO();
    
    s1.str+="1"
    console.log(s1.str); // "1" OK
    console.log(s2.str); // ""  OK
    
    s1.arr.push(1);
    console.log(s1.arr); // [1] Ok
    console.log(s2.arr); // []  Ok

    【讨论】:

    • 我明白,但是通过将数组初始化放在构造函数中不知何故,整个原型概念无关紧要。
    【解决方案2】:

    因为两个实例共享同一个[[Prototype]](分配给SomeO.prototype的Object),所以在SomeO.prototype.arr中也共享同一个Array。

    你可以自己查:

    s1.arr === s2.arr
    

    为了避免这种情况,您可以在构造函数中定义数组(以及您可能需要的所有其他对象):

    function SomeO() {
        this.arr = [];
        this.obj = {}; // define all arrays and objects in the constructor if they need to be separate
    }
    

    【讨论】:

      【解决方案3】:

      因为这就是您定义数组的方式:您在原型上创建 一个 数组对象,该对象在所有实例之间共享。通常,您只想将函数和常量值放在原型上。每个实例属性都需要在构造函数中创建:

      function SomeO() {
          this.arr = [];
      }
      

      【讨论】:

        【解决方案4】:

        当你引用一个对象的属性时(例如s1.arr),它首先检查该属性是否存在于对象上,如果存在则返回它,如果不存在则回退到对象的原型.

        当您执行s1.str += "1"(等效于s1.str = s1.str + "1")时,您将在对象本身上设置str 属性,原型的str 属性不会改变。 s1.str 将从 s1 返回新字符串,s2.str 将回退到 prototype.str

                  s1's str   s2's str   prototype's str   s1.str            s2.str
        before:   -          -          ""                "" (from proto)   "" (from proto)
        after:    "1"                   ""                "1" (from own)    "" (from proto)
        

        当您执行s1.arr.push(1) 时,您会从原型中获得s1.arr,并且您会更改其值。你永远不会在s1 上设置arr 属性。

                  s1's arr   s2's arr   prototype's arr   s1.arr            s2.arr
        before:   -          -          []                [] (from proto)   [] (from proto)
        after:    -          -          [1]               [1] (from proto)  [1] (from proto)
        

        【讨论】:

          猜你喜欢
          • 2015-10-20
          • 1970-01-01
          • 1970-01-01
          • 2012-08-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-05
          • 2014-02-13
          相关资源
          最近更新 更多