javascript继承奇异性
为什么下面的“Cat.prototype=new哺乳类()”行在Cat()函数内部不起作用,但在Cat()函数外部起作用javascript继承奇异性,javascript,inheritance,Javascript,Inheritance,为什么下面的“Cat.prototype=new哺乳类()”行在Cat()函数内部不起作用,但在Cat()函数外部起作用 function Mammal() { Mammal.prototype.hasHair = function() { return true; } } alert( new Mammal().hasHair() ); // dispays true here function Cat() { Cat.prototype = new Mammal(); } tr
function Mammal() {
Mammal.prototype.hasHair = function() { return true; }
}
alert( new Mammal().hasHair() ); // dispays true here
function Cat() {
Cat.prototype = new Mammal();
}
try {
new Cat().hasHair(); // doesn't work. why?
} catch ( err ) {
alert('error'); // displays error here
}
Cat.prototype = new Mammal(); // same line as inside Cat() function
alert( new Cat().hasHair() ); // now it works
我尝试了几种不同的javascript实现,所以我怀疑这是一种实现特性。我想知道这主要是出于好奇,但也仅仅是为了组织,我想在Cat的函数中定义Cat,而不是到处传播。因为
原型成员在执行构造函数之前被传递到对象实例
因此,上面的代码可以工作,但是如果您首先注释了newcat()代码>行它不会,因为在new Cat().hasHair()
行上,Cat的原型没有hasHair()
方法,因为prototype
成员在执行构造函数之前被传递到对象实例
因此,上面的代码可以工作,但是如果您首先注释了newcat()代码>行它不会,因为在新的Cat().hashiir()
行上,Cat的原型没有hashiir()
方法我有点困惑。你到底期望什么
您正在将一个函数从Cat
分配到原型链中,但您是在调用构造函数时这样做的。如果像new Cat().hasHair()
那样调用它,则调用对象根本不知道该函数
在实际调用构造函数之前,需要扩展.prototype
。我有点困惑。你到底期望什么
您正在将一个函数从Cat
分配到原型链中,但您是在调用构造函数时这样做的。如果像new Cat().hasHair()
那样调用它,则调用对象根本不知道该函数
在实际调用构造函数之前,需要扩展.prototype
。函数的原型(充当类)是创建新对象时复制的对象。您不应该在构造函数中设置原型的属性
或者:
function Mammal() {
}
Mammal.prototype.hasHair = function(){ return true };
或者这个:
function Mammal() {
this.hasHair = function(){ return true }
}
函数(作为类)的原型是创建新对象时从中复制的对象。您不应该在构造函数中设置原型的属性
或者:
function Mammal() {
}
Mammal.prototype.hasHair = function(){ return true };
或者这个:
function Mammal() {
this.hasHair = function(){ return true }
}
我编辑了你的代码,所以它可以实现你的目标。下面的代码创建一个基类,然后创建一个子类,其样式与您尝试创建基类的样式相同
function Mammal() {
this.hasHair = function() { return true; }
}
alert( new Mammal().hasHair() ); // dispays true here
function Cat() {
Mammal.call(this);
}
try {
alert( new Cat().hasHair() ); // dispays true here
} catch ( err ) {
alert('error'); // should not fire
}
我编辑了您的代码,以便它能够实现您的目标。下面的代码创建一个基类,然后创建一个子类,其样式与您尝试创建基类的样式相同
function Mammal() {
this.hasHair = function() { return true; }
}
alert( new Mammal().hasHair() ); // dispays true here
function Cat() {
Mammal.call(this);
}
try {
alert( new Cat().hasHair() ); // dispays true here
} catch ( err ) {
alert('error'); // should not fire
}
在执行new Cat
时,将创建一个从Cat.prototype
继承的空对象。什么是Cat.prototype
?它是一个空对象,因为您尚未修改它
在构造器内部,您正在分配Cat.prototype=new demal()代码>。Cat
的下一个实例将继承自此哺乳动物
实例。但是,创建第二个实例也将创建另一个哺乳动物
实例,第三个猫
实例从中继承,依此类推
您最终得到了这个继承链(catX
是Cat
的第x个实例,malemax
是malemal
的第x个实例):
每个Cat
实例都有自己的原型,这在某种程度上与原型的用途相反(共享公共代码)。这看起来可能没什么大不了的,但它有几个后果,包括:
- 增加内存使用:(几乎)每个
Cat
实例都有一个对应的哺乳动物
实例,因此您有2N
对象,而不是N+1
- 继承测试中断:
instanceof
通过比较原型来工作,并且由于cat0
的原型不同于Cat.prototype
(创建多个实例后),Cat
的实例将产生false
您真正想要的继承链是:
cat0 -> Mammal.prototype
cat1 -> Mammal.prototype
cat2 -> Mammal.prototype
...
切勿在构造函数内为原型赋值(或覆盖原型)。构造函数只应设置特定于实例的属性(在某些情况下,您可能希望更改静态属性,但这些属性不太常见)
在构造函数功能之外设置原型:
function Mammal() {}
Mammal.prototype.hasHair = function() { return true; }
function Cat() {
Mammal.apply(this, arguments);
}
Cat.prototype = Object.create(Mammal.prototype);
Cat.prototype.constructor = Cat;
Object.create
创建从作为参数传递的对象继承的对象。请参阅。在执行新Cat
时,将创建一个从Cat.prototype
继承的空对象。什么是Cat.prototype
?它是一个空对象,因为您尚未修改它
在构造器内部,您正在分配Cat.prototype=new demal()代码>。Cat
的下一个实例将继承自此哺乳动物
实例。但是,创建第二个实例也将创建另一个哺乳动物
实例,第三个猫
实例从中继承,依此类推
您最终得到了这个继承链(catX
是Cat
的第x个实例,malemax
是malemal
的第x个实例):
每个Cat
实例都有自己的原型,这在某种程度上与原型的用途相反(共享公共代码)。这看起来可能没什么大不了的,但它有几个后果,包括:
- 增加内存使用:(几乎)每个
Cat
实例都有一个对应的哺乳动物
实例,因此您有2N
对象,而不是N+1
- 继承测试中断:
instanceof
function Cat() {
}
Cat.prototype = new Mammal();
new Cat().hasHair();