JavaScript原型继承的四个常见陷阱与正确实践
本文深入解析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原型继承中需要注意的几个关键问题,希望能为读者提供有价值的参考。
ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
