一文带你搞懂原型(prototype)和原型链(prototype chain)
原型(prototype)和原型链(prototype chain)是 JavaScript 中两个重要的概念,理解它们有助于掌握 JavaScript 的继承机制和对象的属性查找机制。
原型 (Prototype)
在 JavaScript 中,每个对象都有一个隐藏的内置属性 [[Prototype]],它要么是另一个对象,要么是 null。我们通常通过 __proto__ 属性访问这个属性(虽然不推荐直接使用这个属性)。这个 [[Prototype]] 指向的对象称为该对象的原型。
当你创建一个对象时,可以通过对象的构造函数的 prototype 属性来指定这个对象的原型。
例如:
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
console.log(`Hello, my name is ${this.name}`);
};
const alice = new Person("Alice");
alice.greet(); // 输出: Hello, my name is Alice
在这个例子中,Person 是一个构造函数,Person.prototype 是一个对象,包含了一个方法 greet。当我们用 new Person('Alice') 创建一个新对象时,这个新对象的 [[Prototype]] 属性会被设置为 Person.prototype。
原型链 (Prototype Chain)
当访问一个对象的属性时,JavaScript 引擎会首先检查这个对象本身是否有这个属性。如果没有,它会沿着 [[Prototype]] 链向上查找,直到找到该属性或到达原型链的末尾(即 null)。
这个由对象及其原型构成的链条就称为原型链。
例如:
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const alice = new Person('Alice');
console.log(alice.hasOwnProperty('name')); // 输出: true
console.log(alice.hasOwnProperty('greet')); // 输出: false
console.log(alice.**proto**.hasOwnProperty('greet')); // 输出: true
alice.greet(); // 输出: Hello, my name is Alice
在上面的例子中,当我们调用 alice.greet() 时,JavaScript 引擎会在 alice 对象中查找 greet 方法。因为 alice 本身没有 greet 方法,JavaScript 引擎会沿着原型链向上查找,最终在 Person.prototype 中找到了 greet 方法并调用它。
原型链的延伸
原型链可以是多层的。例如:
function Animal() {}
Animal.prototype.walk = function () {
console.log("Walking...");
};
function Person(name) {
this.name = name;
}
Person.prototype = Object.create(Animal.prototype);
Person.prototype.constructor = Person;
Person.prototype.greet = function () {
console.log(`Hello, my name is ${this.name}`);
};
const bob = new Person("Bob");
bob.walk(); // 输出: Walking...
bob.greet(); // 输出: Hello, my name is Bob
在这个例子中,Person.prototype 设置为 Animal.prototype 的一个新对象。因此,bob 对象的原型链是:
- bob 本身
- Person.prototype
- Animal.prototype
- Object.prototype
- null
当我们调用
bob.walk()时,JavaScript 引擎会沿着原型链查找walk方法,最终在Animal.prototype中找到。
总结
- 原型:每个对象都有一个内部属性
[[Prototype]],指向它的原型。 - 原型链:当访问一个对象的属性时,JavaScript 引擎会沿着对象的
[[Prototype]]链向上查找,直到找到该属性或到达链的末尾。 - 理解原型和原型链是掌握 JavaScript 面向对象编程的重要基础。通过这两个概念,JavaScript 实现了继承和属性共享机制。