原型和原型链
对象
在 JavaScript 中,对象是无序属性的集合,其属性可以包含基本值、对象或者函数(方法)。你可以将对象简单地看作是一个包含键值对(Key-Value pairs)的容器。
const user = {
name: "Alice",
age: 25,
greet: function() {
console.log("Hello, I'm " + this.name);
}
};
// 访问对象属性
console.log(user.name); // "Alice"
user.greet(); // "Hello, I'm Alice"
原型
每个 JavaScript 对象(除了 null)在创建时,都会与另一个对象自动关联。这个被关联的对象就被称为原型。对象可以从它的原型上“继承”属性和方法。
原型涉及两个容易混淆的概念:
__proto__(隐式原型):这是每一个对象都有的内部属性(在规范中称为[[Prototype]]),它指向该对象的原型。prototype(显式原型):这是只有函数才拥有的属性。当你使用new关键字通过构造函数创建实例时,实例对象的__proto__会自动指向构造函数的prototype。
// 构造函数
function Person(name) {
this.name = name; // 定义在实例上的属性
}
// 在构造函数的 prototype 对象上添加方法
Person.prototype.sayHello = function() {
console.log("Hi!");
};
const alice = new Person("Alice");
// 实例的隐式原型指向构造函数的显式原型
console.log(alice.__proto__ === Person.prototype); // true
原型链
原型链是 JavaScript 实现继承的底层机制。
当你在一个对象上访问某个属性或方法时,JavaScript 引擎会执行以下查找过程:
- 首先,在对象自身的属性中查找。如果找到,就直接使用。
- 如果没有找到,引擎会顺着对象的
__proto__属性,去它的原型对象中查找。 - 如果原型对象中依然没有,就继续去原型的原型中查找。
- 以此类推,顺藤摸瓜,直到找到该属性,或者到达原型链的顶端(
Object.prototype.__proto__,它的值是null)。 - 如果到了
null还没找到,就返回undefined。
这种由 __proto__ 属性将各个对象串联起来的链式结构,就是原型链。