1. JavaScript原型链机制解析
当我在2013年第一次深入理解JavaScript原型链时,那种顿悟感至今难忘。作为一门基于原型的语言,JavaScript的继承机制与传统面向对象语言截然不同。让我们从一个实际案例开始:
javascript复制function Car(brand) {
this.brand = brand;
}
Car.prototype.getBrand = function() {
return this.brand;
};
const myCar = new Car('Tesla');
console.log(myCar.getBrand()); // 输出'Tesla'
这个简单例子揭示了原型链的三个关键点:
1.1 构造函数与原型对象
每个JavaScript函数(除了箭头函数)都有一个prototype属性,这个属性指向一个对象,我们称之为原型对象。当使用new操作符调用函数时:
- 创建一个新对象
- 将新对象的[[Prototype]]指向构造函数的prototype属性
- 将this绑定到新对象并执行构造函数
- 如果构造函数没有返回对象,则返回新对象
重要提示:ES6的class语法只是原型继承的语法糖,底层机制完全相同
1.2 原型链查找机制
当访问对象属性时,JavaScript引擎会:
- 先在对象自身属性中查找
- 如果找不到,则沿着[[Prototype]]链向上查找
- 直到找到属性或到达null(Object.prototype.proto)
javascript复制console.log(myCar.toString()); // 虽然myCar没有toString方法,但通过原型链找到了Object.prototype.toString
1.3 原型链的终点
所有原型链的终点都是Object.prototype.proto,即null。这意味着:
javascript复制console.log(Object.prototype.__proto__); // null
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. JavaScript继承的多种实现方式
在实际项目中,我尝试过所有主流继承方式,每种都有其适用场景。让我们分析最常见的五种实现:
2.1 原型链继承
javascript复制function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a noise.`);
};
function Dog(name) {
this.name = name;
}
// 关键继承步骤
Dog.prototype = new Animal();
const dog = new Dog('Rex');
dog.speak(); // Rex makes a noise.
问题:
- 所有实例共享引用类型属性
- 无法向父类构造函数传参
2.2 构造函数继承
java复制
