前言
首先给大家介绍一下__proto__属性:__proto__属性指向当前对象的原型对象,即构造函数的prototype属性。
实际上,该属性在ES标准定义中的名字应该是[[Prototype]],具体实现是由浏览器代理自己实现,谷歌浏览器的实现就是将[[Prototype]]命名为__proto__,是用于返回该对象的原型。
我们将通过以下代码分析整个流程:
function Person(name) {
this.name = name
}
let person = new Person('阳')
下图是我画的整个流程图:
首先我们要牢记三点:
我们需要牢记三点:
__proto__和constructor属性是对象所独有的,因为只有有构造函数才能创建对象。因为函数也是一种对象(函数和Object都是Function创建的对象),所以函数也拥有__proto__和constructor属性
prototype属性是函数所独有的。
Function.prototype是function类型,而且它的__proto__属性指向Object.prototype,这是为了兼容以前的js代码。
接下来,我们来一步一步的分析:
原型链
如上图所示,红色框部分为原型链。
流程如下:
Person构造函数通过new Person()创建了person实例。- 实例是一个对象,所以拥有
__proto__属性(也就是实例的原型),指向Person的原型Person.prototype,而Person.prototype也是对象,所以下面也有__proto__属性,指向Object的原型Object.prototypeObject.prototype也是对象,所以下面也有__proto__属性,指向null
当创建person实例以后,实例就继承了构造函数的原型以及私有属性以及方法,当使用某个属性或者方法的时候,会先从实例自身找,如果没有找到就通过原型找构造函数,如果构造函数还是没有这个属性或者方法,那就通过原型继续往对象顶层的Object对象寻找,Object是一个顶层对象,浏览器也定义了很多方法属性,比如Object.create,如果Object里面没有这个方法或者属性,由于Object的原型的原型指向了null,因此会报undefined 未定义。
以上就是整个原型链,以及原型链的意义。
Person函数与Function
这里需要注意的是,Function中F为大写,他是一个浏览器内置的函数,与Object类似。而我们这里的Person函数,是一个普通的构造函数。那么他们之间有什么关系呢?我相信有很多初学者的同学有这样一个疑问,普通的函数是怎么来的呢?由谁创建的呢?答案就是,由Function创建的,Function是一个构造函数,普通函数之所以可以称之为函数对象,就是因为由Function构造函数创建的。下面我们结合上面的图来理一下他们的关系,主要从constructor属性,以及原型两个方面。
Person函数的原型为Person.prototype,那么Person.prototype对象的构造函数就是Personperson实例的构造函数比较特殊,是继承了Person.prototype的构造函数,也就是person实例的构造函数也是Person函数。- 那么
Person函数的构造函数是谁呢?当然是创建他的Function函数