我一直在深入挖掘JavaScript,努力为我正在开发的项目建立一个健全,可维护的继承模型。我遇到了一些很棒的资源,one of which指出了一个有趣的问题,它将“类”的原型指向另一个“类”的新实例。它使用this article来说明这一点。
具体来说,文章指出通过以下代码创建“Cat”实例(从上面链接的第二篇文章中提取)将导致每个“Cat”实例指向同一个“Mammal”实例
function Mammal(name){
this.name=name;
this.offspring=[];
}
Mammal.prototype.haveABaby=function(){
var newBaby=new Mammal("Baby "+this.name);
this.offspring.push(newBaby);
return newBaby;
}
Mammal.prototype.toString=function(){
return '[Mammal "'+this.name+'"]';
}
Cat.prototype = new Mammal();
Cat.prototype.constructor=Cat;
正如指出这篇文章的文章(上面链接的第一篇文章)所示,使用此代码会产生以下结果:
var myPet = new Cat('Felix');
myPet.haveABaby();
var myPet2 = new Cat('Garfield');
myPet2.haveABaby();
console.log(myPet2.offspring); // returns ["","",...]
因此,myPet2在其后代数组中有两个元素。这并不理想,因为它只有一个孩子。
这一切都对我有意义;然而,令人困惑的是,如果您将this.offspring=[]
更改为this.offspring=0
然后将this.offspring.push(newBaby)
更改为this.offspring++
,则每个新的“Cat”实例似乎都将其后代属性设置为0
var myPet = new Cat('Felix');
myPet.haveABaby();
var myPet2 = new Cat('Garfield');
myPet2.haveABaby();
console.log(myPet2.offspring); // returns 1
所以,myPet2有1个后代。这是应该发生的事情。
为什么每次都会重置this.offspring
,而array / .push()方法却没有?我最初的想法是它将某个数组视为一个对象,因此Mammal类型的任何“后代”属性将始终引用相同的东西,而整数是每次重新创建的原始值。 。是
无论哪种方式,这两种结果是否相互矛盾,至于是否为每只新猫创造了一个新的哺乳动物实例?
答案 0 :(得分:1)
Cat的每个实例都会创建一个具有原型Mammal的Object对象的新实例。请注意,虽然只有一个Mammal实例,但两个Cats中的this
都是Cat的单独实例,而不是Mammal。发生的事情不是因为两个Cat共享一个Mammal原型,而是因为数组是引用,而不是值。
因此,虽然有两个Cats并且两个Cats this
都是独立的实例,但它们都共享相同的数组offspring
。
这说明了在没有混淆对象,构造函数和原型的情况下发生的事情:
var a=[];
var b=a;
a.push('hello');
alert(b[0]); // alerts 'hello'.
将此与javascript(字符串和数字)中的值进行对比:
var a=0;
var b=a;
a++;
alert(b); // alerts 0
引用类型(数组和对象)仅指向底层对象。因此,当将具有引用类型的变量分配给另一个变量时,它们共享同一个对象(仅复制地址,而不是对象本身)。
相反,当分配给另一个变量时,会复制值类型(数字和字符串)。
这样做的一个微妙的副作用是你可以通过将其中一个重新分配给另一个数组来打破Cats之间的共享后代引用:
myPet.offspring = [new Mammal('Kitty'), new Mammal('Spot')];
alert(myPet2.offspring.length); // alerts 0
// Because the code above causes the
// `offspring` property of myPet to
// point to a different array.
答案 1 :(得分:0)
今天已经回答了这个问题,你可以在这里找到它:
https://stackoverflow.com/a/26337868/1641941
这些mdn文章看起来不像Mozilla开发者网络文章我建议使用这个文章,因为它没有创建Parent的实例来设置继承的原型部分并且不会修改你不喜欢的对象#39;拥有实现简单任务作为继承: