JavaScript原型继承的四个常见陷阱与正确实践

作者:青柠时间:2026-10-22 07:54:52浏览:587

本文深入解析JavaScript原型继承中易错的四个关键点:原型对象覆盖导致方法丢失、使用对象字面量重置原型、实例与__proto__的固定指向关系,以及原型上引用类型属性的共享问题。通过对比错误与正确代码示例,帮助开发者避免继承陷阱,掌握正确的原型定义方式。

JavaScript原型继承的四个常见陷阱与正确实践

在使用原型链进行继承时,必须谨慎处理原型上的方法和属性定义,否则可能会引发非预期的运行结果。

谨慎定义原型上的方法

一、谨慎定义原型上的方法

在为构造函数的原型添加方法时,务必确保在重新赋值原型对象之后再进行定义。如果在更改原型之前定义方法,新原型对象将不包含该方法,从而导致调用失败。例如:


function superObj(){}
superObj.prototype.sayHi=function sayHi(){
  console.log('hi');
};
superObj.prototype={
  name:'Poly'
};
var obj=new superObj();
obj.sayHi();//报错!! superObj.sayHi is not a function

正确的操作方式如下:


function superObj(){}
superObj.prototype={
  name:'Poly'
};
superObj.prototype.sayHi=function sayHi(){
  console.log('hi');
};
var obj=new superObj();
obj.sayHi();// 'hi'

避免使用对象字面量直接创建属性或方法

二、避免使用对象字面量直接创建属性或方法

若直接使用对象字面量语法,会创建一个全新的对象,并将该新对象的引用地址赋值给构造函数的prototype属性。这会导致原有的原型链断裂。示例如下:


function superObj(){}
superObj.prototype={
  sayHi:function sayHi(){
    console.log('hi');
  }
}

正确的操作方式如下:


function superObj(){}
superObj.prototype.sayHi=function sayHi(){
  console.log('hi');
}

理解对象实例与原型之间的直接对应关系

三、理解对象实例与原型之间的直接对应关系

这意味着每个实例的__proto__属性始终指向其构造函数的原型对象。即使后续修改了构造函数的prototype属性,之前已经创建的实例中的__proto__引用也不会发生改变。示例如下:


function superObj(){}
superObj.prototype.say=function() {
  console.log('hello');
}
var obj=new superObj();
superObj.prototype={
  say:function() {
    console.log('world');
  }
};
var obj2=new superObj();
obj.say();//'hello'
obj2.say();//'world'

避免在原型上定义值为引用类型的属性

四、避免在原型上定义值为引用类型的属性

如果在原型上定义值为引用类型(如数组或对象)的属性,所有实例将共享该属性的值(因为它们指向同一个内存地址)。当其中一个实例修改该引用类型的值或属性时,所有其他实例中的对应属性也会随之改变。因此,值为引用类型的属性建议在构造函数内部定义。示例如下:


function superObj(){}
superObj.prototype.ary=[1,2,3];
var obj1=new superObj();
var obj2=new superObj();
obj1.ary[0]=0;//obj1.ary和obj2.ary指向的是同一个数组,当obj1修改此数组时,obj2.ary也会发生改变
console.log(obj2.ary[0]);//0

如果希望各个实例拥有独立的引用对象,避免相互影响,则应在构造函数内部进行定义。示例如下:


function superObj(){
  this.ary=[1,2,3];
}
var obj1=new superObj();
var obj2=new superObj();
obj1.ary[0]=0;//obj1.ary和obj2.ary指向的不是同一个数组,所以修改obj1.ary不会影响obj2.ary
console.log(obj2.ary[0]);//1

以上内容详细讨论了JavaScript原型继承中需要注意的几个关键问题,希望能为读者提供有价值的参考。

作者最新文章