👩🚀 摘要:本文主要深入介绍了__proto__
和prototype
这两个属性,顺着这个思路讲解了原型链的形成过程。
从一个很迷惑的经典题目开始。
Object instanceof Function //true
Function instanceof Object //true
首先,明确这里的Object
和Function
都是指JS中的内置函数对象。然后,为了讲透这个关系,我们从两个属性入手,原型__proto__
和原型对象prototype
。
二者之间的关系是一个对象的__proto__
指向创建该对象的构造函数的prototype
。
二者的作用是用来实现基于原型的继承。我们通常所说的原型链,就是,一条由__proto__
串起来的prototype
的链。如果原型链是糖葫芦,__proto__
就是木棒,prototype
就是山楂。我们来看一个详细的实现继承的例子。
function Parent () {}
function Child () {}
Child.prototype = new Parent();
var instance = new Child();
代码如上,其中最关键的一步就是Child.prototype = new Parent();
。这行代码使Child
的原型对象的原型指向Parent
的原型对象,Child
的原型对象可以继承Parent
的原型对象上的属性和方法。
画出其中的原型链(蓝线所示),我们来一步步探究上面发生了什么。
图中,蓝色线表示原型链指向,其中,实线是实例对象instance
的原型链,虚线是其他对象的原型指向。黄色线是原型对象指向。
-
线【1】:对应
var instance = new Child();
。当我们用构造函数Child
来生成一个实例instance
的时候,其内部属性__proto__
指向其构造函数Child
的原型对象Child.prototype
。 -
线【2】:对应
Child.prototype = new Parent();
。由于我们将Child
的原型对象手动更改成了Parent
的一个实例,所以Child
的原型对象的构造函数编程Parent
,它的__proto__
指向Parent.prototype
。 -
线【3】:对应
function Parent(){}
。新创建一个函数的时候,相当于通过var Parent = new Object()
创建一个对象,所以Parent.prototype
的__proto__
指向Object.prototype
。 -
由函数指向
Function.prototype
的几条蓝色虚线:内置的一些生成类型对象的函数,例如,Object|Number|Stirng|Array|Function
等,以及用function(){}
的方式创建的函数以及都相当于通过new Function()
得来,所以,其__proto__
指向Function.prototype
。 -
最后我们看到
Function.prototype
指向Object.prototype
。这也是JS内置的,这也就是我们常说的函数本身也是对象。 -
Object.prototype
的__proto__
是什么呢,不是所有对象都有__proto__
么,JS中规定,它的原型是null
。原型链到此为止。还有一点需要注意的是,JS内在规定,Funtion.prototype
是一个函数。console.log(typeof Object.prototype); //object console.log(typeof Function.prototype); //function
这样顺着图中原型链一找,不难得出Function
和Object
互相在对方原型链上。