原型链(Prototype Chain) 是 JavaScript 实现继承的核心机制。简单来说,每个对象都有一个原型对象(prototype
),通过这个原型对象,可以访问它继承的属性和方法。如果在一个对象上找不到某个属性或方法,就会沿着原型链向上查找,直到找到或者到达原型链的顶端(null
)。
基础概念
1. 原型对象(prototype
):
每个函数(包括构造函数)都有一个 prototype
属性,指向一个对象,这个对象包含了可以被实例继承的属性和方法。
2. 对象的 __proto__
属性:
每个对象都有一个隐式属性 __proto__
,它指向创建该对象的构造函数的 prototype
。
通过 __proto__
,形成了对象与原型的链接。
3. 原型链:
如果一个对象没有找到某个属性或方法,会顺着它的 __proto__
一直向上查找,直到 null
(表示原型链的终点)。
例子
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function () {
console.log(`Hello, my name is ${this.name}`);
};
const alice = new Person('Alice');
alice.sayHello(); // 输出:Hello, my name is Alice
console.log(alice.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
原型链的结构
以下是上面代码中原型链的关系:
-
alice
是Person
的实例:-
alice
的__proto__
指向Person.prototype
。
-
-
Person.prototype
:-
Person.prototype
的__proto__
指向Object.prototype
。
-
-
Object.prototype
:-
Object.prototype
的__proto__
是null
,表示原型链的终点。
-
alice --> Person.prototype --> Object.prototype --> null
属性查找的规则
当访问一个对象的属性时,JavaScript 会按照以下规则查找:
- 先查找对象自身是否有这个属性。
- 如果没有,就顺着
__proto__
向上查找原型对象。 - 如果一直找到
null
都没有,就返回undefined
。
示例:
console.log(alice.name); // 'Alice',在 alice 对象上找到
console.log(alice.sayHello); // 找到 Person.prototype 上的方法
console.log(alice.toString()); // 找到 Object.prototype 上的方法
console.log(alice.nonExistent); // undefined,没有找到
原型链的优势
1. 代码复用: 可以通过共享 prototype
上的方法和属性,避免重复定义。
2. 实现继承: 子类可以通过原型链继承父类的属性和方法。
注意事项
1. 性能问题:
- 如果原型链太长,属性查找会变慢。
2. 避免误操作:
- 修改
prototype
时要小心,可能会影响所有实例。
总结
- 原型链是 JavaScript 中对象继承的基础。
- 每个对象都有一个原型,通过原型链可以访问继承的属性和方法。
- 如果属性或方法在当前对象上不存在,JavaScript 会自动沿着原型链向上查找。