接 上文 原型链,今天我们来说说终极原型链
# 终极原型链
只要对 js
深入了解一些,你肯定听说过一句话就是函数本质上也是一个对象,当函数被当作做对象去使用时函数就被称为函数对象,当函数被 ()
调用是一个函数。既然函数也是对象,那它肯定也有一个原型。本文讲解将一直以下面代码为例
function Person(name, age) { // 创建一个 Person 构造函数 | |
this.name = name; | |
this.age = age; | |
} | |
const obj = new Person("asuhe", 18); //new 一个 Person 实例 | |
console.log(obj); |
所有的函数对象都会有一个原型(ES6 箭头函数除外),且会有一个 prototype
属性指向该原型。当用一个函数对象当作构造函数使用 new
创建一个实例对象时,该构造函数所有实例对象的隐式原型即 __proto__
都会指向构造函数的原型对象。在上述代码中我们可以得到一个最基本的原型链结构
函数对象的原型本质上也是一个对象,只要是对象那么必定会有一个构造函数。** 实际上除函数对象和自身指定构造函数的对象外,所有的对象都是由 Object
这个构造函数 new
出来的。** 也就是说函数对象的原型是由 Object
构造出来的。根据原型链查找规则,我们可以用如下代码证明
let res = {}; | |
console.log(res); | |
console.log(res.__proto__ === Person.prototype.__proto__); //true 说明普通对象都是由 Object 作为构造函数 new 出来的 |
Object
作为构造函数那么它必然也有一个原型并且由 prototype
属性指向。上面我们说过除函数对象和自己指定构造的对象外,所有的对象都是由 Object
作为构造函数 new
出来的。所以我们可以画出更加完善一点的原型链
Object
的原型的隐式原型 __proto__
应该指向其构造函数的原型 prototype
,而 Object
的原型是由它自身 new
出来的。这样它原型链就形成了一个环: ▶ (prototype of Object).__proto__
▶。为了阻止原型链在这个环里无限循环查找下去,所以在底层 (prototype of Object).__proto__
被设置成了 null
。我们可以用代码证明上述的原型链
console.log(Person.prototye.__proto__ === Object.prototype); //true 说明函数对象的原型是由 Object new 出来的 | |
console.log(Object.prototype.__proto__); //null 说明 Object 的原型的隐式原型值为 null |
# 函数对象的原型链
到目前为止,我们基本搞定了普通对象的原型链结构。但是还有一个问题我们没有搞定就是,既然函数也是一个对象那么它肯定也有自己的隐式原型 __proto__
指向它的构造函数的原型。在 js 的底层所有的函数都是由 Function
作为构造函数 new
出来的,也就是说任何一个函数都是 Function
的实例
** 当我们使用 function
关键字时本质上就是 Fuction
作为构造函数 new
了一个对象。在 js 的底层最终都是调用 Function
函数去创建一个函数的。** 我们可以使用如下代码证明
// 证明所有的函数对象都是由 Function 构造的 | |
console.log(Person.__proto__ === Function.prototype); // true | |
console.log(Object.__proto__ === Function.prototype); // true | |
console.log(Person.__proto__ === Object.__proto__); // true | |
// 箭头函数没有 prototype | |
const arrFn = ()=> console.log('ash'); | |
console.log(arrFn.prototype); //undefined 说明箭头函数没有原型 | |
console.log(arrFn.__proto__ === Function.prototype); //true 说明箭头函数同样是 Function new 出来的 |
而 Function
函数本身也是一个函数对象,但是 Function
它是由自己 new 出来的。所以它的 __proto__
和 prototype
都指向同一个原型。
console.log(Function.prototype === Function.__proto__); //true 说明 Function 自己 new 出的自己 | |
console.log(Function.prototype.__proto__ === Object.prototype); //true 说明 Function 的原型还是 Object new 出来的 |
有了以上基础我们就可以继续完善一下原型链
上面这个图就是我们常说的终极原型链了
# 自测题
// 思考下列输出并说明原因 | |
console.log(Object instanceof Object) | |
console.log(String instanceof Function) | |
console.log(Function instanceof Object) | |
console.log(Object instanceof Function) | |
console.log(String instanceof Object) |