在JavaScript中,基于原型的继承机制是JavaScript对象系统的基础。这种继承机制不是通过传统的类层次结构实现的,而是通过原型链(prototype chain)来实现的。下面是一个步骤详解,介绍如何在JavaScript中实现基于原型的继承机制。
1. 定义构造函数和原型对象
首先,你需要定义一个构造函数,它用于初始化新创建的对象。然后,你可以在这个构造函数的prototype
属性上添加方法和属性,这些方法和属性将被所有通过该构造函数创建的对象所共享。
function Parent(name) {
this.name = name;
}
Parent.prototype.sayHello = function() {
console.log("Hello, " + this.name);
};
2. 创建子构造函数并设置其原型
接下来,你需要创建一个子构造函数。为了让这个子构造函数创建的对象能够继承父构造函数创建的对象的属性和方法,你需要将子构造函数的prototype
设置为一个父构造函数创建的实例的原型。但是,通常我们不会直接这样做,因为这样会导致子构造函数创建的实例共享父实例的属性(即这些属性会变成静态的)。相反,我们会将子构造函数的prototype
设置为一个新的对象,这个新对象的原型是父构造函数的prototype
。
function Child(name, age) {
Parent.call(this, name); // 借用构造函数继承属性
this.age = age;
}
// 设置Child的prototype的原型为Parent的prototype
Child.prototype = Object.create(Parent.prototype);
// 修正constructor属性,因为它现在指向Parent
Child.prototype.constructor = Child;
// 在Child的原型上添加新的方法或属性
Child.prototype.sayAge = function() {
console.log(this.name + " is " + this.age + " years old.");
};
3. 实例化子对象并测试
现在,你可以通过new
关键字来创建子构造函数的实例,并测试它是否继承了父构造函数的属性和方法。
var child1 = new Child("Charlie", 10);
child1.sayHello(); // 继承自Parent
child1.sayAge(); // Child特有的方法
console.log(child1 instanceof Child); // true
console.log(child1 instanceof Parent); // true,因为child1的原型链中包含Parent.prototype
4. 注意事项
- 当你修改原型对象上的属性时,这些修改会影响到所有继承自该原型的实例。但是,如果你在某个实例上直接添加了一个与原型上同名的属性,那么这个实例会“遮蔽”掉原型链上同名的属性。
- 构造函数中的
this
关键字指向新创建的对象实例。在子构造函数中,你可以通过Parent.call(this, arguments)
的方式来“借用”父构造函数的属性初始化逻辑(这种方式称为“借用构造函数”继承)。 - 原型链的查找是从对象的
__proto__
属性(或Object.getPrototypeOf(obj)
)开始的,一直向上直到null
。如果在某个原型对象上找到了所需的属性或方法,则停止查找并返回结果;如果没有找到,则返回undefined
。