原型和原型链(由深入浅)Function 和 Object 的前世今生

1,902 阅读3分钟

序言

原型和原型链属于老生常谈的话题。首先,原型和原型链属于js语言高阶范畴,也是js语言的基石。
相信很多小伙伴都看过各种各样的教程以及解读,这次我们从不同的角度来深挖一下。

基础概念介绍

function 和 Function

在js语言中function是一个关键字用来声明一个函数对象。

// 函数声明(Function Declaration)
function f(){};

// 函数表达式Function Expression)
const f = function(){};

// new Function构造函数
// 不建议通过Function的方式去声明函数对象
// 因为在给这个对象添加属性(书写其方法)的时候,会再一次的解析代码
const f = new Function();

其中关于函数表达式和函数声明的区别,感兴趣的自行查阅

函数声明方式构建函数本质是new Function()创建了对应的函数对象,只有函数对象才有原型对象prototype,只要是对象必有隐式原型__proto__(指向构造此对象的函数的原型对象prototype)

原型

js之父在设计js原型、原型链的时候遵从以下两个准则:

function Person() {

}

const person = new Person()

// 准则1:原型对象(即Person.prototype)的constructor指向构造函数本身
Person.prototype.constructor === Person
// 准则2:实例(即person)的__proto__和原型对象指向同一个地方
person.__proto__ === Person.prototype

// 每个对象都有 __proto__ 属性,但只有函数对象才有 prototype 属性

为了可读性以及表述清晰下文中 原型 指代隐式原型__proto__ES5标准中是使用[[prototype]]来指代, 原型对象 指代显示原型prototype

原型链

提到原型链就不得不掏出传家宝

Javascript _Object_Layout.png

整体原型链分析

我们先放出原型链的底层实现顺序结论

首先:js中先创建的是Object.prototype这个原型对象。  
然后:在这个原型对象的基础之上创建了Function.prototype这个原型对象。  
其次:通过这个原型对象创建出来Function这个构造函数。   
最后: 又通过Function这个构造函数创建了function Object()这个构造函数对象。
/*
 除了Object的原型对象(Object.prototype)的__proto__指向null
 其他内置函数对象的原型对象和自定义构造函数的__proto__都指向Object.prototype
 因为原型对象本身是普通对象
 */

很多原型链说明解析都是从浅入深,今天我们就有深入浅来讲解一下,一些说明都会从上面的原型链图找到依据。 从图中最右侧我们可以清除的看到Object的原型对象的原型__proto__是null。这其实是万物皆对象这句话的开端,js引擎创建了Object.prototype这个对象所以此对象的原型是null。然后通过Object.prototype这个对象构建了Function.prototype这个原型对象。然后借由Function.prototype创建了Function函数图中就是 Function via new Function(so points it is own proto!)这一段。Function是特殊的Function作为函数对象它的原型__proto__指向了Function.prototype这表明了它是自己构建了自己。Object是通过new Function()来创建的。

从上面一段说明来引申出了js最关键的两个构造函数Object和Function,因为js中一切复杂类型都是由它们来作为基石构建出来的,搞清楚这两个构造函数原型原型链就非常好理解了。

因为我在学习原型和原型链的过程中一直没有理解透彻的就是 Function 和 Object 这一块,当初感觉很绕,因为使用的少也没有深究,最近准备基础知识复习深究了一下,有什么补充的和有争议的地方欢迎小伙伴提出,语言组织偏个人习惯和理解,望理解。