JavaScript 原型继承机制与构造函数冲突解决

作者:青柠

时间:2026-10-24

浏览:105

本文深入解析JavaScript基于原型的对象系统,阐明构造器与实例间的原型关系。重点探讨原型继承中constructor属性指向错误的常见陷阱,并提供重置constructor及通过静态变量调用父类方法的高级解决方案,辅以完整代码示例。

文章目录

JavaScript原型继承基础

在JavaScript中,对象本身并不直接拥有原型属性,而构造器(Constructor)才具备原型对象。


原型的核心含义在于:若构造器定义了一个原型对象A,那么由该构造器创建的所有实例都将自动继承并复制自对象A。


具体实现代码如下:

 
/*申明2个构造器*/
var flower=function(){
this.name="nokia";
} 
var flower2=function(){
this.age=22;
} 
/*原型链*/
flower2.prototype=new flower();
/*根据刚才原型的定义,实例obj必然复制自new flower();*/
obj=new flowe2();
/*从父类继承的属性*/
alert(obj.name); //==>"nokia"
alert(obj.age); //==>22

通常情况下,由构造器生成的实例,其constructor属性默认指向该构造器本身。


alert(obj.constructor);//==>flower


同时,构造器原型(prototype)上的constructor属性也指向该构造器自身。


alert(flower.prototype.constructor==flower);//==>true


constructor属性冲突与解决

然而,在使用原型继承时,constructor属性往往会出现指向冲突的问题。


相关代码如下:

 
function flower(){}
function flower2(){}
flower2.prototype=new flower();
var obj1=new flower();
var obj2=new flower2();
/*问题出现了,2个实例的constructor属性都指向flower*/
alert(obj1.constructor==obj2.constructor);
/*obj1和obj2是不同的构造器产生的实例,缺指向相同的构造器,显然出了问题*/

针对上述问题的解决方法如下:


具体代码实现为:

 
flower2.prototype=new flower();
/*重置原型后,修改原型的constructor属性*/
flower2.prototype.constructor=flower2
或者,在每次构造实例时手动重写constructor属性。
function flower2(){
this.constructor=arguments.callee;
} 
flower2.prototype=new flower();

父类方法调用的高级实现

此外,标准的原型继承机制并未直接提供调用父类方法的途径。


为弥补这一缺陷,我们可以基于原型继承,利用静态变量记录父类信息来实现对父类方法的调用。


相关实现代码如下:

 
var Class={
create:function()
{ 
var _class=function()
{ 
this.init.apply(this,arguments);
} 
_class.prototype.init=Function.prototype.init;
try{
return _class;
}finally{
_class=null;
} 
} 
}; 
//默认构造函数
Function.prototype.init=function(){}
//方法扩展
Function.prototype.extend=function(list)
{ 
for(var i in list)this.prototype[i]=list[i];
return this;
} 
//多级继承
Function.prototype.inherits=function(parent)
{ 
//继承的深度级别
var _depth=0;
//方法属性移植
this.extend(new parent());
//初始化构造函数 类的继承通常不继承构造函数
this.prototype.init=Function.prototype.init;
//类的静态父类
this.parent=parent;
//执行父类函数
this.prototype.parent=function(name)
{ 
//若没有参数则执行构造函数
if(!name)name='init';
//即将执行的父类
var _parent=parent;
//若当前已经在父类中执行则继续向上寻找超类
if(_depth)
{ 
for(var i=0;i<_depth;i++)
{ 
_parent=_parent.parent;
} 
} 
//设置好级别
_depth++;
try{
//执行函数并返回值
return _parent.prototype[name].apply(this,Array.prototype.slice.apply(arguments,[1]));
}catch(e){
throw(e);
}finally{
//恢复级别
_depth--;
} 
} 
return this;
} 

示例演示如下:


具体代码为:

 
//创建名为class1的构造器
var class1=Class.create().extend({
b:function()
{ 
alert('clas');
alert(this.c);
}, 
c:100
}); 
//创建"对象"(构造器)的实例
var s=new class1();
s.b();// ==>"clas",100

关于继承父类并调用其方法的实现:


代码如下:

 
var test=Class.create().inherits(class1).extend({
b:function()
{ 
alert('test');
this.parent('b')
}, 
c:110
}); 

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章