我对通过原型设计实现继承感到困惑,而且这个' 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'即使什么都没被推?
答案 0 :(得分:1)
因为tony
和peter
共享数组,person
。只有一个数组,你只是改变它的状态。
创建tony
和peter
之后,您就会记住这一点(省略细节):
+−−−−−−−−−−+ 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__ |−−−−+ +−−−−−−−−−−−+
您可以通过tony
和peter
拥有 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
对象。所以这个人的胃正在改变。
如果你给person
和peter
他们自己的胃,那么一切都会好起来的。)。
tony
修改强> 刚看到@wookieb回答 - 它甚至比我的好。