javascript oop,instanceof和基类

Joh*_*ny5 11 javascript oop polymorphism

我在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();
Run Code Online (Sandbox Code Playgroud)

first.sayWhoAmI(); 记录这个:

first derivation is a Derivation1 : true
first derivation is a Derivation2 : false
first derivation is a BaseObject : false
Run Code Online (Sandbox Code Playgroud)

second.sayWhoAmI();这一情况记录:

second derivation is a Derivation1 : false
second derivation is a Derivation2 : true
second derivation is a BaseObject : false
Run Code Online (Sandbox Code Playgroud)

我觉得这两个firstsecond对象应该说他们是实例BaseObject.

我知道可能不会为此制作JavaScript,但我想知道是否有办法实现这一点.

Fel*_*ing 10

只有调用Base.apply(...)不会设置继承.所有这一切.apply都是设置this第一个参数,没有别的.调用父构造函数很重要,但这还不够.

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

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

Derivation1.prototype = new Base();
Run Code Online (Sandbox Code Playgroud)

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

所以我们需要的是一个继承自的对象Base.prototype,幸运的是,ECMASCript 5定义了一个可以为我们做这个的函数(polyfill):

 Derivation1.prototype = Object.create(Base.prototype);
Run Code Online (Sandbox Code Playgroud)

这将创建一个继承自的新对象Base.prototype.现在,由于您使用新对象替换了原始原型,constructor因此必须设置该属性以使其正确指向Derivation1:

Derivation1.prototype.constructor = Derivation1;
Run Code Online (Sandbox Code Playgroud)

以下是一个完整的例子.还要看看这个小提琴TJ 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();
Run Code Online (Sandbox Code Playgroud)