JavaScript原型链继承机制详解与注意事项

作者:木棉

时间:2026-10-27

浏览:162

本文详细解析JavaScript中基于原型链的继承实现方式。通过将子类的prototype属性设置为父类的实例,子类可自动继承父类的所有属性和方法。文章重点探讨了原型链中instanceof运算符的特殊行为,以及重写prototype导致的constructor指向Object而非子类的现象,并提供了相应的代码示例与测试说明。

文章目录

原型链继承的基本实现

若采用原型方式重新定义前文示例中的类,其结构将调整为以下形式:

代码如下:

function ClassA() {
}
ClassA.prototype.color = "blue";
ClassA.prototype.sayColor = function () {
 alert(this.color);
};
function ClassB() {
}
ClassB.prototype = new ClassA();

原型方式的核心在于最后一行代码。此处将 ClassB 的 prototype 属性赋值为 ClassA 的实例。这一做法的精妙之处在于,无需逐个将 ClassA 的属性和方法添加到 ClassB 的 prototype 中,即可直接获取 ClassA 的所有属性和方法。将 ClassA 的实例赋予 prototype 属性,是实现这一目标的有效手段。

注意:在调用 ClassA 构造函数时,并未传递任何参数。这是原型链中的标准做法,务必确保构造函数不接收参数。

与对象冒充类似,子类的所有属性和方法必须在 prototype 属性被赋值之后进行定义。若在赋值前添加方法,这些方法将被销毁,因为 prototype 属性已被替换为新对象。因此,为 ClassB 类添加 name 属性和 sayName() 方法的代码如下:

代码如下:

function ClassB() {
}
ClassB.prototype = new ClassA();
ClassB.prototype.name = "";
ClassB.prototype.sayName = function () {
 alert(this.name);
};

原型链继承的测试示例

可通过运行以下示例来验证代码逻辑:


代码如下:

var objA = new ClassA();
var objB = new ClassB();
objA.color = "blue";
objB.color = "red";
objB.name = "John";
objA.sayColor();
objB.sayColor();
objB.sayName();

instanceof运算符与constructor指向问题

此外,在原型链机制下,instanceof 运算符的行为也较为独特。对于 ClassB 的所有实例,instanceof 运算符对 ClassA 和 ClassB 均返回 true。例如:


代码如下:

var objB = new ClassB();
alert(objB instanceof ClassA); //输出 "true"
alert(objB instanceof ClassB); //输出 "true"

在 ECMAScript 的弱类型环境中,这是一个非常有用的工具,但在使用对象冒充时无法通过该方法进行判断。然而,由于子类的原型被直接重新赋值,会出现以下情况:


代码如下:

console.log(objB.__proto__===objB.constructor.prototype) //false

这是因为 ClassB 的原型链 prototype 属性被另一个类的对象所覆盖。从输出结果可以看出,objB.__proto__ 仍然指向 ClassB.prototype,而非 objB.constructor.prototype。这不难理解,因为给 Person.prototype 赋值的是一个对象直接量 new ClassA() 的实例,使用对象直接量方式定义的对象,其构造器(constructor)指向的是根构造器 Object。由于 Object.prototype 是一个空对象 {},它自然与 ClassB.prototype 不相等。


实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章