JavaScript 构造函数继承的三种实现方式
本文深入解析 JavaScript 中基于构造函数的继承机制,详细演示了三种核心实现方案:通过对象冒充模拟伪继承、利用 call 或 apply 方法简化调用,以及基于原型链的原型指向策略。文章还探讨了直接引用原型对象的潜在风险,并介绍了使用空构造函数作为中继对象以隔离父子原型、保持 constructor 属性正确的最佳实践。
构造函数继承概述
在上一篇《JavaScript 原型继承之基础机制》中,我们探讨了原型继承的基本原理。本文将聚焦于如何利用构造函数来实现具体的继承逻辑。
为了直观展示,我们先构建一个描述人类的 People 构造函数:
代码如下:
function People(){
this.race = '愚蠢的人类';
} 接着,定义一个描述黄种人的 Yellow 构造函数:
代码如下:
function Yellow(name, skin){
this.name = name;
this.skin = skin;
} 在 JavaScript 中,要让子类 Yellow 继承父类 People 的属性,可以通过多种技术手段来模拟这一过程。
对象冒充实现继承
1、对象冒充(Object Masquerading)
对象冒充的核心思想是将抽象类的构造函数作为普通函数执行,从而实现伪继承效果:
代码如下:
function Yellow(name, skin) {
this._extend = People;
this._extend();
delete this._extend; //删除对 People 的引用
this.name = name;
this.skin = skin;
}
//实例化 yellow1
var yellow1 = new Yellow('小明', '黄皮肤');
console.log(yellow1.name); //小明
console.log(yellow1.race); //愚蠢的人类 上述代码中,我们为 Yellow 添加了一个私有方法 _extend。由于函数以引用形式存在,执行 _extend() 时会自动调用 People 方法,并传入 Yellow 构造函数的 name 参数。需要注意的是,Yellow 自身的属性和方法定义必须在该过程结束后、外部引用被清除后再进行。
注:通过对象冒充可以实现多重继承
利用 call/apply 简化继承
2、call / apply 方法
使用 call 或 apply 方法实现继承更为简洁,无需繁琐的操作步骤:
代码如下:
function Yellow(name, skin) {
People.apply(this, arguments);
this.name = name;
this.skin = skin;
}
//实例化 yellow2
var yellow2 = new Yellow('大卫', '黑皮肤')
console.log(yellow2.name); //大卫
console.log(yellow2.race); //愚蠢的人类
此处向 apply 传递了 arguments 数组,你也可以选择使用 new Array 或字面量数组形式。 原型链继承与原型隔离
3、原型链(Prototype Chaining)
第一种原型继承方式是将子类的原型直接指向父类的一个实例:
代码如下:
Yellow.prototype = new People();
Yellow.prototype.constructor = Yellow; //初始的 prototype 被完全清空,所以最好将 constructor 重置
var yellow3 = new Yellow('小王', '黄皮肤');
console.log(yellow3.race); //愚蠢的人类 从反向逻辑理解,yellow3 实例本身未定义 race 属性,但其原型链上的 race 属性恰好来源于 People 对象的实例。
若 People 的属性已写入原型中,则无需实例化,只需将 Yellow 的 prototype 指向 People 的 prototype:
代码如下:
function People(){};
People.prototype.race = '愚蠢的人类';
Yellow.prototype = People.prototype;
Yellow.prototype.constructor = Yellow; 这种方式仅改变指针指向,避免了实例化操作,看似高效。但由于引用类型的特性,Yellow 和 People 将共享同一个原型对象。这意味着对 Yellow.prototype.constructor 的修改会直接破坏 People 的原型对象结构。
为了解决这一问题,可以引入一个空的中继对象来绕过父类原型:
代码如下:
var F = function(){};
F.prototype = People.prototype;
Yellow.prototype = new F();
Yellow.prototype.constructor = Yellow;JS中将数组和对象混合组装为JSON字符串
2026-11-05 16:41:42
JS运算符优先级与结合性的区别是什么?
2026-11-05 13:22:02
JS Map怎么只遍历Key或Value
2026-11-05 13:00:36
D3.js 与 ECharts 选型对比:灵活性 vs 开发效率
2026-11-05 09:45:01
为什么JS中typeof []返回object:数组类型检测误区解析
2026-11-04 19:50:47
