实例,构造函数,Function,Object关系

481 阅读3分钟

前言

首先给大家介绍一下__proto__属性:__proto__属性指向当前对象的原型对象,即构造函数的prototype属性。

实际上,该属性在ES标准定义中的名字应该是[[Prototype]],具体实现是由浏览器代理自己实现,谷歌浏览器的实现就是将[[Prototype]]命名为__proto__,是用于返回该对象的原型

我们将通过以下代码分析整个流程:

function Person(name) {
    this.name = name
}
let person = new Person('阳')

下图是我画的整个流程图:

image-20210621144616124

首先我们要牢记三点:

我们需要牢记三点:

  • __proto__constructor属性是对象所独有的,因为只有有构造函数才能创建对象。因为函数也是一种对象(函数和Object都是Function创建的对象),所以函数也拥有__proto__constructor属性

  • prototype属性是函数所独有的。

  • Function.prototypefunction类型,而且它的__proto__属性指向Object.prototype,这是为了兼容以前的js代码。

接下来,我们来一步一步的分析:

原型链

如上图所示,红色框部分为原型链。

流程如下:

  • Person 构造函数通过 new Person() 创建了 person 实例。
  • 实例是一个对象,所以拥有__proto__属性(也就是实例的原型),指向Person的原型Person.prototype,而Person.prototype也是对象,所以下面也有__proto__属性,指向Object的原型Object.prototype
  • Object.prototype也是对象,所以下面也有__proto__属性,指向 null

当创建person实例以后,实例就继承了构造函数的原型以及私有属性以及方法,当使用某个属性或者方法的时候,会先从实例自身找,如果没有找到就通过原型找构造函数,如果构造函数还是没有这个属性或者方法,那就通过原型继续往对象顶层的Object对象寻找,Object是一个顶层对象,浏览器也定义了很多方法属性,比如Object.create,如果Object里面没有这个方法或者属性,由于Object的原型的原型指向了null,因此会报undefined 未定义。

以上就是整个原型链,以及原型链的意义。

Person函数与Function

这里需要注意的是,FunctionF为大写,他是一个浏览器内置的函数,与Object类似。而我们这里的Person函数,是一个普通的构造函数。那么他们之间有什么关系呢?我相信有很多初学者的同学有这样一个疑问,普通的函数是怎么来的呢?由谁创建的呢?答案就是,由Function创建的,Function是一个构造函数,普通函数之所以可以称之为函数对象,就是因为由Function构造函数创建的。下面我们结合上面的图来理一下他们的关系,主要从constructor属性,以及原型两个方面。

  • Person函数的原型为Person.prototype,那么Person.prototype对象的构造函数就是Person
  • person实例的构造函数比较特殊,是继承了Person.prototype的构造函数,也就是person实例的构造函数也是Person函数。
  • 那么Person函数的构造函数是谁呢?当然是创建他的Function函数