我正在用JavaScript设计一些类层次结构。到目前为止,它运行良好,但我不知道如何确定对象是否是父类的"实例"。示例:
function BaseObject(name){
this.name = name;
this.sayWhoAmI = function(){
console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1));
console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2));
console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject));
};
}
function Derivation1(){
BaseObject.apply(this, ['first derivation']);
}
function Derivation2(){
BaseObject.apply(this, ['second derivation']);
}
var first = new Derivation1();
var second = new Derivation2();
first.sayWhoAmI();
记录此:
first derivation is a Derivation1 : true
first derivation is a Derivation2 : false
first derivation is a BaseObject : false
而second.sayWhoAmI();
记录这个:
second derivation is a Derivation1 : false
second derivation is a Derivation2 : true
second derivation is a BaseObject : false
我觉得first
和second
对象都应该说它们是BaseObject
的实例。
我知道JavaScript可能不是为此而设计的,但我想知道是否有办法实现这一点。
仅调用Base.apply(...)
不会设置继承。.apply
所做的只是将this
设置为第一个参数,没有其他任何操作。调用父构造函数很重要,但这还不够。
你要做的是正确地设置原型链。也就是说,您必须将Derivation1.prototype
设置为继承自Base.prototype
的内容。
由于构造函数的每个实例都继承自构造函数的原型,因此您将看到诸如之类的代码
Derivation1.prototype = new Base();
这是一个坏主意,您已经看到了原因:Base
期望参数设置特定于实例的属性(在本例中为name
)。但我们并不关心这些属性,因为我们稍后将在子构造函数中使用Base.apply(this, ...)
初始化它们。
因此,我们只需要一个从Base.prototype
继承的对象,幸运的是,ECMASCcript 5定义了一个可以为我们实现这一点的函数(polyfill):
Derivation1.prototype = Object.create(Base.prototype);
这将创建一个继承自Base.prototype
的新对象。现在,由于用新对象替换了原始原型,因此必须设置constructor
属性,使其正确指向Derivation1
:
Derivation1.prototype.constructor = Derivation1;
下面是一个完整的例子。也可以看看这把小提琴和T.J.Crowder的精彩回答,它解释了基本上相同的问题,但可能以更好的方式。
示例:
function BaseObject(name){
this.name = name;
}
// move properties shared by all instances to the prototype!
BaseObject.prototype.sayWhoAmI = function() {
console.log(this.name + ' is a Derivation1 : ' + (this instanceof Derivation1));
console.log(this.name + ' is a Derivation2 : ' + (this instanceof Derivation2));
console.log(this.name + ' is a BaseObject : ' + (this instanceof BaseObject));
};
function Derivation1(){
BaseObject.apply(this, ['first derivation']);
}
Derivation1.prototype = Object.create(BaseObject.prototype);
Derivation1.prototype.constructor = Derivation1;
// some useless method of the child "class"
Derivation1.prototype.someOtherMethod = function() {
return 42;
};
var first = new Derivation1();
first.sayWhoAmI();