JavaScript中的对象继承是一种机制,它允许一个对象(子对象)继承另一个对象(父对象)的属性和方法。这种机制在JavaScript中是通过原型链实现的。
在JavaScript中,每个对象都有一个内部属性[[Prototype]]
,它指向另一个对象,即该对象的原型。当我们试图访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript会沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的末端(即null
)。
JavaScript中的继承主要有以下几种类型:
[[Prototype]]
指向父对象来实现继承。以下是一个简单的原型链继承示例:
function Animal(name) {
this.name = name;
}
Animal.prototype.sayName = function() {
console.log('My name is ' + this.name);
};
function Dog(name, breed) {
Animal.call(this, name); // 调用父类构造函数
this.breed = breed;
}
// 设置Dog的原型为Animal的实例,实现继承
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 修复构造函数指向
Dog.prototype.sayBreed = function() {
console.log('My breed is ' + this.breed);
};
var myDog = new Dog('Buddy', 'Golden Retriever');
myDog.sayName(); // 输出: My name is Buddy
myDog.sayBreed(); // 输出: My breed is Golden Retriever
问题:原型链继承可能会导致不必要的属性共享,尤其是当父对象的属性是引用类型时。
解决方法:使用组合继承或寄生组合式继承,通过在子构造函数中调用父构造函数来避免这个问题。
function inheritPrototype(subType, superType) {
var prototype = Object.create(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 指定对象
}
// 父类
function SuperType(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
};
// 子类
function SubType(name, age) {
SuperType.call(this, name); // 第二次调用SuperType()
this.age = age;
}
// 继承方法
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function() {
console.log(this.age);
};
var instance1 = new SubType('Evan', 18);
instance1.colors.push('black');
console.log(instance1.colors); // ['red', 'blue', 'green', 'black']
instance1.sayName(); // Evan
instance1.sayAge(); // 18
var instance2 = new SubType('Nicholas', 29);
console.log(instance2.colors); // ['red', 'blue', 'green']
instance2.sayName(); // Nicholas
instance2.sayAge(); // 29
在这个例子中,SubType
的每个实例都有自己的colors
属性副本,避免了引用共享的问题。
领取专属 10元无门槛券
手把手带您无忧上云