JavaScript 继承机制详解:对象冒充与原型链
本文深入解析 JavaScript 的两种核心继承机制:对象冒充与原型链。对象冒充通过临时属性或 call/apply 方法实现,但存在内存浪费且无法继承原型属性。原型链利用 __proto__ 链接解决共享问题,却难以在实例化时向父类传参。文章最后推荐结合两者优势的混合继承模式,并详细演示代码实现与注意事项。
JavaScript 继承机制概述
在 JavaScript 中,实现继承主要依赖两种机制:对象冒充(Object Masquerading)和原型链(Prototype Chain)。
对象冒充实现与缺陷
一、对象冒充实现方式 对象冒充主要包含三种具体实现路径:临时属性法、call() 方法以及 apply() 方法。
代码示例如下:
function Person(name){
this.name = name;
this.say = function(){
alert('My name is '+this.name);
}
}
function F2E(name,id){
this.temp = Person;
this.temp(name);
delete this.temp;
this.id = id;
this.showId = function(){
alert('Good morning,Sir,My work number is '+this.id);
}
}
var simon = new F2E('Simon',9527);
simon.say();
simon.showId();2. call()/apply() 方式
这种方式的本质在于改变函数内部 this 指针的指向对象。
代码示例如下:
function Person(name){
this.name = name;
this.say = function(){
alert('My name is '+this.name);
}
}
function F2E(name,id){
Person.call(this,name); //apply()方式改成Person.apply(this,new Array(name));
this.id = id;
this.showId = function(){
alert('Good morning,Sir,My work number is '+this.id);
}
}
var simon = new F2E('Simon',9527);
simon.say();
simon.showId();缺点分析:首先观察内存分配情况:
![]() |
在面向对象概念中,执行 new 实例化后,对象会在堆内存中开辟独立空间。需要注意的是,成员方法定义在代码段中,且理论上方法是共用的。然而,通过对象冒充方式继承时,所有成员方法都直接指向 this 实例。这意味着每次 new 操作后,每个实例都会创建一份独立的方法副本,而非共用,从而导致严重的内存浪费。此外,对象冒充无法继承通过 prototype 定义的变量和方法。如下代码执行时会报错:
代码示例如下:
function Person(name){
this.name = name;
this.say = function(){
alert('My name is '+this.name);
}
}
Person.prototype.age = 20;
Person.prototype.sayAge = function(){alert('My age is '+this.age)};
function F2E(name,id){
Person.apply(this,new Array(name));
this.id = id;
this.showId = function(){
alert('Good morning,Sir,My work number is '+this.id);
}
}
var simon = new F2E('Simon',9527);
simon.sayAge(); //提示TypeError: simon.sayAge is not a function二、原型链方式
原型链原理与局限性
代码示例如下:
function Person(){
this.name = 'Simon';
}
Person.prototype.say = function(){
alert('My name is '+this.name);
}
function F2E(id){
this.id = id;
this.showId = function(){
alert('Good morning,Sir,My work number is '+this.id);
}
}
F2E.prototype = new Person();
var simon = new F2E(9527);
simon.say();
simon.showId();
alert(simon.hasOwnProperty('id')); //检查是否为自身属性接下来结合上述示例深入理解 JS 原型链概念:
![]() |
原型链可理解为:JS 中每个对象均包含一个隐藏的 __proto__ 属性。实例化对象的 __proto__ 指向其所属类的 prototype 属性;若该 prototype 被赋值为另一个实例化对象,则该新对象的 __proto__ 又指向其类的 prototype,如此循环形成一条链。这正是前文代码中
代码示例如下:
F2E.prototype = new Person()
这句关键语句的作用。当 JS 对象访问某个属性时,会先查找自身属性,若未找到则沿原型链依次向上查找。由于原型链上的方法是共用的,因此解决了对象冒充导致的内存浪费问题。
下面分析其缺点: 缺点同样明显:采用原型链方式继承时,实例化子类时无法向父类传递参数。这也是为何前例中 function Person() 没有参数,而是直接硬编码 this.name='Simon' 的原因。以下代码无法达到预期效果:
代码示例如下:
function Person(name){
this.name = name;
}
Person.prototype.say = function(){
alert('My name is '+this.name);
}
function F2E(name,id){
this.id = id;
this.showId = function(){
alert('Good morning,Sir,My work number is '+this.id);
}
}
F2E.prototype = new Person();
var simon = new F2E("Simon",9527);
simon.say();
simon.showId();
function Person(name){
this.name = name;
}
Person.prototype.say = function(){
alert('My name is '+this.name);
}
function F2E(name,id){
this.id = id;
this.showId = function(){
alert('Good morning,Sir,My work number is '+this.id);
}
}
F2E.prototype = new Person(); //此处无法进行传值,this.name或者name都不行,直接写F2E.prototype = new Person('wood')是可以的,但是这样的话simon.say()就变成了My name is wood
var simon = new F2E("Simon",9527);
simon.say(); //弹出 My name is undefined
simon.showId();
混合继承模式推荐
最后,总结一种较为理想的继承实现方式:成员变量采用对象冒充,成员方法采用原型链。代码示例如下:
代码示例如下:
function Person(name){
this.name = name;
}
Person.prototype.say = function(){
alert('My name is '+this.name);
}
function F2E(name,id){
Person.call(this,name);
this.id = id;
}
F2E.prototype = new Person();
//此处注意一个细节,showId不能写在F2E.prototype = new Person();前面
F2E.prototype.showId = function(){
alert('Good morning,Sir,My work number is '+this.id);
}
var simon = new F2E("Simon",9527);
simon.say();
simon.showId();JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28


