终极原型链


接{% post_link ‘2021-10-20-原型与原型链’ ‘上文’%}原型链,今天我们来说说终极原型链

终极原型链

只要对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__都会指向构造函数的原型对象。在上述代码中我们可以得到一个最基本的原型链结构

原型链(1)

函数对象的原型本质上也是一个对象,只要是对象那么必定会有一个构造函数。**实际上除函数对象和自身指定构造函数的对象外,所有的对象都是由Object这个构造函数new出来的。**也就是说函数对象的原型是由Object构造出来的。根据原型链查找规则,我们可以用如下代码证明

let res = {};
console.log(res);
console.log(res.__proto__ === Person.prototype.__proto__); // true 说明普通对象都是由Object作为构造函数new出来的

原型链(1)

Object作为构造函数那么它必然也有一个原型并且由prototype属性指向。上面我们说过除函数对象和自己指定构造的对象外,所有的对象都是由Object作为构造函数new出来的。所以我们可以画出更加完善一点的原型链

原型链(2)

Object的原型的隐式原型__proto__应该指向其构造函数的原型prototype,而Object的原型是由它自身new出来的。这样它原型链就形成了一个环:$Object.prototype$ ▶(prototype of Object).__proto__▶$Object.prototype$。为了阻止原型链在这个环里无限循环查找下去,所以在底层(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出来的

有了以上基础我们就可以继续完善一下原型链

原型链(3)

上面这个图就是我们常说的终极原型链了

自测题

// 思考下列输出并说明原因
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)