每个函数都有一个prototype的属性,当我们以这个函数为构造函数创建实例时(即用new的形式),创建出来的这个对象是没有prototype的属性的。
以下代码为例:
在console里进行调试
cf 拥有一个prototype的属性,这个属性就叫做原型。这个原型本身是一个对象cf{},我们叫它原型对象。
cf 的原型对象有一个constructor的属性,它就是构造函数。我们可以看到,这个构造函数是cf本身。(当然它还有一些别的属性。)
cf1 作为 cf 的实例,它拥有了cf.prototype里的所有属性。把cf1展开看一下:
可以看到cf1 有一个隐式属性_proto_,这个属性是无法通过ECMA语句访问到的。它指向了cf.prototype这个原型对象,这就是原性链。
原型对象本身作为ECMA内置对象Object的一个实例,它也有_proto_,指向的是Object.prototype,这就构成了一个链表的结构。
这个链表就决定了在查找属性时的顺序。例如ECMA在查找 cf1.p1时,会先查找它本身,若没有p1这个属性,再沿着_proto_找。
在这里 new 操作符所做的事情,可以分为以下:
1、建立一个新对象cf1 var cf1 = cf{ };
2、将cf1的_proto_指向原型对象 cf1._proto = cf.prototype
3、将cf1作为this的参数,调用构造函数cf。 cf.call(cf1)