关于这个'的困惑和JavaScript中的原型

时间:2017-09-02 10:48:39

标签: javascript

我对通过原型设计实现继承感到困惑,而且这个' JavaScript中的关键字。



let person = {
  stomach: [],

  eat(food) {
    this.stomach.push(food);
  }
};

let tony = {
  __proto__: person
};

let peter = {
  __proto__: person
};

tony.eat("shawarma");
alert( tony.stomach ); // shawarma


alert( peter.stomach ); // shawarma




在上面的例子中,为什么最后一行给出了答案' shawarma'即使什么都没被推?

4 个答案:

答案 0 :(得分:1)

因为tonypeter 共享数组,person。只有一个数组,你只是改变它的状态。

创建tonypeter之后,您就会记住这一点(省略细节):

                               +−−−−−−−−−−+                   
person−−−−−−−−−−−−−−−−−−−+−+−−>| (Object) |                   
                        / /    +−−−−−−−−−−+      +−−−−−−−−−−−+ 
                        | |    | stomach  |−−−−−>|  (Array)  | 
                        | |    +−−−−−−−−−−+      +−−−−−−−−−−−+ 
                        | |                      | length: 0 |
                        | |                      +−−−−−−−−−−−+ 
         +−−−−−−−−−−−+  | |
tony−−−−>| (Object)  |  | |
         +−−−−−−−−−−−+  | |
         | __proto__ |−−+ |
         +−−−−−−−−−−−+    |
                          |
         +−−−−−−−−−−−+    |
peter−−−>| (Object)  |    |
         +−−−−−−−−−−−+    |
         | __proto__ |−−−−+
         +−−−−−−−−−−−+

无论您是通过tony.__proto__.stomach还是peter.__proto__.stomach(通过原型链)访问该数组,您只能访问该数组。当您通过"shawarma"推送eat时,该数组的状态会被修改,并且无论您走哪条路径都可以看到它:

                               +−−−−−−−−−−+                   
person−−−−−−−−−−−−−−−−−−−+−+−−>| (Object) |                   
                        / /    +−−−−−−−−−−+      +−−−−−−−−−−−−−−−+ 
                        | |    | stomach  |−−−−−>|    (Array)    | 
                        | |    +−−−−−−−−−−+      +−−−−−−−−−−−−−−−+ 
                        | |                      | length: 1     |
                        | |                      | 0: "shawarma" |
         +−−−−−−−−−−−+  | |                      +−−−−−−−−−−−−−−−+
tony−−−−>| (Object)  |  | |
         +−−−−−−−−−−−+  | |
         | __proto__ |−−+ |
         +−−−−−−−−−−−+    |
                          |
         +−−−−−−−−−−−+    |
peter−−−>| (Object)  |    |
         +−−−−−−−−−−−+    |
         | __proto__ |−−−−+
         +−−−−−−−−−−−+

您可以通过tonypeter 拥有 stomach来解决此问题,并可能从{{1}移除stomach (如果你想直接使用person并将其用作原型,你可以保留它):

person

答案 1 :(得分:0)

tony.hasOwnProperty("stomach")将返回false(因为它不是其他OO语言所谓的属性)并且现在是原型的一部分(如类属性静态成员)。原型对于使用它的每个对象都是通用的。

因此,person__proto__ prototype stomach的任何对象都会共享相同的class Person{ constructor(){ this.stomach = []; } eat(food){ this.stomach.push(food); } } const tony = new Person(); const peter = new Person(); class RandomPelo extends Person{ constructor(){ super(); this.randomness = true; } eat(food){ super.eat(food); this.weird_shared_stomach.push(food); } } const pelo = new RandomPelo();

您可以使用ES6代替:

class

NB:
RandomPelo.prototype.weid_shared_stomach = [];关键字只是围绕构造函数概念的语法糖,因此您也可以修改其原型以添加"静态"属性:

{{1}}

答案 2 :(得分:0)

因为“胃”是原型的属性,对于tony和peter对象来说完全相同。您需要在构造函数中为每个新创建的对象重新初始化“胃”属性。

同时尽量避免引用 proto https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto

let person = {
  stomach: [], // You may or may not want to remove this, depending
  eat(food) {
    this.stomach.push(food);
  }
};

let tony = {
  __proto__: person,
  stomach: []
};

let peter = {
  __proto__: person,
  stomach: []
};

tony.eat("shawarma");
console.log(tony.stomach);  // shawarma

console.log(peter.stomach); // empty

答案 3 :(得分:0)

这是因为#include<stdio.h> int main(void) { char a = 01212; printf("%d",a); return 0; } tony共享包含peter属性的person原型。

当您触发stomach时,tony.eat('shawarma')方法正在启动,eat指向this对象。所以这个人的胃正在改变。

如果你给personpeter他们自己的胃,那么一切都会好起来的。)。

tony

修改 刚看到@wookieb回答 - 它甚至比我的好。