问题 javascript oop,instanceof和基类


我在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,但我想知道是否有办法实现这一目标。


8188
2017-07-26 01:25


起源

只有打电话 Base.apply(...) 没有设置继承。你必须正确设置原型。看到: jsfiddle.net/fkling/wJE6s。另请查看此问题以获得解释: stackoverflow.com/questions/3145700/... - Felix Kling
菲利克斯你应该把它写成答案,这正是我所需要的,你的小提琴只是简单地证明了这一点。不要让别人窃取你的声誉! - Johnny5
同意他应该添加答案,但他可能并不担心将他的代表提高0.01%! - jahroy
已经很晚了,我太累了,无法提供完整的答案,对不起。现在添加一个,我希望这是可以理解的。如果有任何不清楚的地方,请毫不犹豫地发表评论。 - Felix Kling


答案:


只有打电话 Base.apply(...) 没有设置继承。这一切 .apply 确实是设定 this 第一个论点,没有别的。调用父构造函数很重要,但这还不够。

您需要做的是正确设置原型链。也就是说,你必须设置 Derivation1.prototype 从继承的东西 Base.prototype

由于构造函数的每个实例都继承自构造函数的原型,因此您将看到如下代码

Derivation1.prototype = new Base();

这是 一个坏主意 你已经可以看出原因了: Base 期望参数设置实例特定属性(name 在这种情况下)。但是我们并不关心这些属性,因为我们稍后会在子构造函数中初始化它们 Base.apply(this, ...)

所以我们需要的是一个继承自的对象 Base.prototype 幸运的是,ECMASCript 5定义了一个可以为我们做的功能(填充工具):

 Derivation1.prototype = Object.create(Base.prototype);

这将创建一个继承自的新对象 Base.prototype。现在,既然您用新对象替换了原始原型,则必须设置 constructor 财产,使其正确指向 Derivation1

Derivation1.prototype.constructor = Derivation1;

以下是一个完整的例子。另外看看 这个小提琴  和 T.J.的这个优秀答案克劳德,它解释了基本相同的问题,但也许更好的方式。


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();


10
2017-07-26 12:13