JavaScript 多级继承和 isPrototypeOf

标签 javascript inheritance multi-level

我有一个用 JavaScript 实现的多级继承,如下所示

function MovingObject(){

}

function Vehicle(){

}
Vehicle.prototype = Object.create(MovingObject);

function Car(){

}
Car.prototype = Object.create(Vehicle);

var c = new Car();

Car 是 Vehicle 的子级,而 Vehicle 又是 MovingObject 的子级,因此我期望 Car 是 MovingObject 的间接子级。

以下语句返回 true,表明 Car 是 Vehicle 的直接子级

Vehicle.isPrototypeOf(c);

但是,下面的语句不会返回 true

MovingObject.isPrototypeOf(c);

知道为什么它不返回 true,以及如何让它返回 true

最佳答案

这是有关 JavaScript 的常见问题。

MovingObjectVehicle构造函数,但它们不是原型(prototype)。

也就是说,您应该使用 Object.create(ConstructorFunction.prototype) 进行派生,而不仅仅是 ConstructorFunction

在 JavaScript 中,即使是函数也是对象,这就是为什么当您提供构造函数时 Object.create(...) 可以工作。生成的对象将以构造函数对象作为原型(prototype)。

实际上,您可以使用 Object.create(ConstructorFunction.prototype) 方法,也可以使用 new 实现相同的目标:

Vehicle.prototype = new MovingObject();

new 方法的主要问题是您正在使用构造函数创建一个新对象,并且可能会向原型(prototype)添加不需要的数据和行为:

function MovingObject() {
  this.x = 11;
}

function Vehicle() {}
Vehicle.prototype = new MovingObject();

var instance = Object.create(Vehicle.prototype);

// What? instance has "x" property!!
document.getElementById("result").textContent = instance.x;
<div id="result"></div>

更新

OP在一些评论中说:

Does that mean we cannot establish a true is-a relationship between Car and MovingObject here? If yes, how can we test it using code? Meaning, I want to execute some code only if Car is-a Moving object. How can I achieve the test?

为了更清楚,检查并执行以下代码片段:

function A() {}

function B() {}
B.prototype = Object.create(A.prototype);

function C() {}
C.prototype = Object.create(B.prototype);

var instanceOfB = Object.create(B.prototype);
var instanceOfC = Object.create(C.prototype);

var result1 = A.prototype.isPrototypeOf(instanceOfC);
var result2 = B.prototype.isPrototypeOf(instanceOfC);
var result3 = A.prototype.isPrototypeOf(instanceOfB);

document.getElementById("result1").textContent = result1;
document.getElementById("result2").textContent = result2;
document.getElementById("result3").textContent = result3;
<h2>A is prototype of instanceOfC?</h2>
<div id="result1"></div>
<h2>B is prototype of instanceOfC?</h2>
<div id="result2"></div>
<h2>A is prototype of instanceOfB?</h2>
<div id="result3"></div>

更新2

正如 @RobertRossmann 对此答案的评论,可以使用 instanceof 运算符实现相同的代码片段,该运算符的附加值是可以有效检查实例是否属于提供构造函数的某个原型(prototype)功能:

function A() {}

function B() {}
B.prototype = Object.create(A.prototype);

function C() {}
C.prototype = Object.create(B.prototype);

var instanceOfB = Object.create(B.prototype);
var instanceOfC = Object.create(C.prototype);

var result1 = instanceOfC instanceof B;
var result2 = instanceOfC instanceof C;
var result3 = instanceOfB instanceof A;
var result4 = instanceOfC instanceof A;

document.getElementById("result1").textContent = result1;
document.getElementById("result2").textContent = result2;
document.getElementById("result3").textContent = result3;
document.getElementById("result4").textContent = result4;
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
<div id="result4"></div>

关于JavaScript 多级继承和 isPrototypeOf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30365958/

相关文章:

r - 使用具有聚类数据的小鼠进行插补

python - 如何将具有字典列的数据框转换为多级数据框

javascript - 当用户移动并按住鼠标时 Canvas 发出警报

javascript - 单击时更改图像

c++ - 如果事先不知道所有的类,如何实现双重调度?

php - 如何在 PHP 中调用 'parent' trait 方法?

inheritance - 以 class-extend.js 风格扩展自定义对象

javascript - 如何在 PHP Laravel 中为货币值设置自动数字 jquery?

javascript - nodejs 意外结果中的 localeCompare 选项