原型的实质就是一个可以被复制的类,类似于一个模板,通过原型可以创建出相同的对象,并且在原型上的方法和属性会被创建出的对象所共享。通过原型创建出来的对象是相互独立的,可以为不同的对象添加不同的属性方法,在对象实例上新添加的方法和属性与其他对象是不共享的。
原型
原型分为两种,隐式原型以及显式原型
- 每一个函数都有显式原型属性prototype,默认指向的是一个空的Object对象(原型对象),每个原型对象都有一个属性constructor,指回到该函数
- 每一个对象都有隐式原型属性__proto__,指向的是该对象的构造函数显示原型的值
function Fn(){
}
let fn=new Fn()
从以上两点可以得出fn.__proto__=Fn.prototype以及Fn.prototype.constructor=Fn
原型链
原型链实际指的是隐式原型链,体现了对象之间的继承关系,当需要访问对象的某个方法或者属性的时候,先在对象本身寻找,若自身没有就沿着原型链向上寻找。
拿Fn以及fn来举例子,fn是Fn的一个实例对象,若我想调用toString方法,就会先去fn自身寻找,发现没有该方法,就会去fn.__proto__也就是Fn的显式原型对象Fn.prototype上去寻找,也没有找到toString方法,但是因为Fn.prototype的本质是一个Object实例对象,所以会继续沿着原型链寻找到Object.prototype,而此时找到了toString方法就可以直接调用。寻找的示意图如下:
注意一下Object原型上存在一个方法叫hasOwnProperty,表示对象自有属性(而不是继承来的属性)中是否具有指定的属性。
构造函数/原型/实例对象的关系(图解)
这张图中需要注意的是所有的函数都是Function的实例对象,包括Function本身,所以所有的函数的__proto__都指向Function.prototype