原型链
个人认为原型链是 js 中解决方法复用的一种机制。
- 每个对象都有一个 proto 属性,该属性指向自己的原型对象
- 每个构造函数都有一个 prototype 属性,该属性指向实例对象的原型对象
- 原型对象里的 constructor 指向构造函数本身
每个对象都有自己的原型对象,而原型对象本身也是对象,也有自己的原型对象,从而形成了一条原型链条,原型链的终点是 NULL
当试图访问一个对象的属性时,首先会在自身搜寻,找不到就会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。instansof 就是原型链寻找算法
instanceof用来判断一个对象是否是某个构造函数的实例。它的实现原理也是基于原型链。instanceof运算符沿着对象的原型链查找,判断是否有一个构造函数的prototype属性在对象的原型链上。

js
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log('Hello, ' + this.name);
};
const alice = new Person('Alice');
// __proto__ 指向实例对象的原型
console.log(alice.__proto__ === Person.prototype); // true
// prototype 指向构造函数的原型
console.log(Person.prototype.constructor === Person); // true
// 原型链的顶端
console.log(Object.prototype.__proto__ === null); // true
// 通过原型链查找属性和方法
alice.greet(); // 输出 'Hello, Alice'
console.log(alice.toString()); // 调用的是 Object.prototype.toString
// instanceof 运算符
console.log(alice instanceof Person); // true
console.log(alice instanceof Object); // true1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Person是一个构造函数,定义了一个属性name和一个方法greet。Person.prototype.greet是添加到Person原型上的方法,所有由Person创建的实例都可以访问这个方法。alice.__proto__指向Person.prototype,这是实例对象的原型。Person.prototype.constructor指向Person构造函数本身。Object.prototype.__proto__是null,表示原型链的顶端。- 访问
alice.greet()时,JavaScript 引擎在alice对象自身没有找到greet方法,于是沿着原型链查找到Person.prototype并调用了该方法。 alice.toString()没有在alice和Person.prototype中找到,于是继续沿着原型链查找到Object.prototype并调用了该方法。alice instanceof Person返回true,因为Person.prototype在alice的原型链上。alice instanceof Object返回true,因为所有对象最终都继承自Object.prototype。