HTML笔记 ·

Javascript 原型链之原型对象、实例和构造函数三者之间的关系

首先来说一下名词解释,首先说一下prototype,每个函数都有一个prototype属性,这个属性是指向一个对象的引用,这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型对象上继承属性和方法。

再来说一下constructor,对象的constructor属性用于返回创建该对象的函数,也就是我们常说的构造函数。

至于__porto__属性,在 javascript 中每个对象都会有一个 __proto__ 属性,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去 __proto__ 里找这个属性,这个 __proto__ 又会有自己的 __proto__,于是就这样一直找下去,也就是我们平时所说的原型链的概念。

先来看一个例子

如上,当我们创建一个函数,系统就会为这个函数自动分配一个prototype指针,指向它的原型对象。并且可以发现,这个原型对象包含两个部分(constructor 和 __proto__)其中constructor指向函数自身。

当我们将该函数作为模版创建实例(new方法)的时候,我们发现创建出的实例是一个与构造函数同名的object,这个object是独立的,他只包含了一个__proto__指针(实例没有prototype,强行访问则会输出undefined),这个指针指向上面提到的构造函数的prototype原型对象。

这时候我们发现三者形成了一个大"闭环"。之所以加上引号,因为构造函数和实例之间无法直接访问,需要通过__proto__指针间接读取。

其实这几个的关系可以通过下图来表现明确一些:Javascript 原型链之原型对象、实例和构造函数三者之间的关系

在javascript当中除了undefined和null外都有__proto__,但是只有function对象才有prototype属性,其他任何类型的值都没有。即使是使用new方法从function构造出的实例对象也没有prototype属性。但是我们可以通过赋值的形式来给他添加,例如:

下面我们在看一下下面这个例子

我们可以发现,改变了prototype之后创建的实例指向了新的prototype对象,而之前的依然指向老的prototype对象。

下面是个应用这个方法拓展实例的小例子:

 

参与评论