回答
- 原型链的设计目的,是为了实现对象的复制,原理是一个对象可以使用其原型链上所有的变量和方法。
- 对象被大体分为三类,原型对象,实例对象,构造函数。三者通过prototype、proto、constructor、new相互关联。
原型对象通过
__proto__
构成的链,称为原型链。构造函数也可以通过__proto__
构成链。分析
原型、构造函数、实例的关系
原型是一种特殊的对象,包含一些特殊的key。
- 构造函数是一种特殊的函数,可以执行并返回一个实例对象。
- 实例是一个普通对象。
原型链、构造函数链
- 原型的上面是原型,组成了一条原型链。
- 构造函数的上面是构造函数,组成了一条构造函数链。
- 在终点处有特殊机制(设计缺陷)防止造成循环,这个特殊机制就是 Function.proto===Function.prototype,这个机制保证了终点是 null。
举个例子:
// @ts-nocheck
class A {}
class B extends A {}
class C extends B {}
console.log(
typeof A, // function
typeof A.prototype, // object
C.__proto__ === B, // true,函数的上面是函数
B.__proto__ === A, // true
A.__proto__ === Function, // false,终点特殊处理
A.__proto__ === Function.prototype, // 终点特殊处理,不再指向Function,而指向Function的原型
// 但 typeof Function.prototype === "function"
C.prototype.__proto__ === B.prototype, // true,原型的上面是原型
B.prototype.__proto__ === A.prototype, // true
A.prototype.__proto__ === Object.prototype, // true
Object.prototype.__proto__ === null // 终点为null
);
原型链是原型的链,顶层为 null
这句话虽然有一些直白,但却可以直接揭示其本质。
我们从一组代码看起,大家可以在浏览器中跑一跑,每行会输出什么?
Object.prototype.__proto__; // null
Function.prototype.__proto__.__proto__; // null
String.prototype.__proto__.__proto__; // null
class A {}
class B extends A {}
class C extends B {}
A.prototype.__proto__.__proto__; // null
B.prototype.__proto__.__proto__.__proto__; // null
C.prototype.__proto__.__proto__.__proto__.__proto__; // null
以上所有的输出均为 null,我们可以用图例表示:
【此处等待补充一张图】
以最后一条为例,文字说明
C.prototype
是「C原型」C.prototype.__proto__
是「B原型」C.prototype.__proto__.__proto__
是「A原型」C.prototype.__proto__.__proto__.__proto__
是「Object原型」C.prototype.__proto__.__proto__.__proto__.__proto__
是「null」
instanceof,isPrototypeOf
inatanceof 针对 function,其右边必须是一个 fucntion;isPrototypeOf 针对 object,其调用者必须是一个 object。