js原型和原型链
原型:
每个函数都有一个prototype属性,这个属性指向这个函数的原型对象,如下:
function Fn () {}
console.log(Fn.prototype)
用图表表示如下:
函数Fn有一个prototype属性,这个属性就指向它的原型对象即Fn.prototype,原型对象又有一个constructor构造器,这个构造器指向Fn函数本身。原型对象里面存放着所有实例对象需要共享的属性和方法!
Fn函数的实例化:
let fn = new Fn()
通过new操作符就可以实例化一个fn对象,画图来看一下他们之间的对应关系
实例对象fn会有一个__proto__属性,它指向构造函数Fn的原型。
上面我没看到了一个Fn.protottype里面有一个__proto__属性,那我们来看看它的指向吧
从图可以看到,Fn.prototype.__proto__指向Object.prototype,这就说明每个函数的原型都是Object的实例,也就是说每个函数的原型都是通过 new Object() 产生的。上面的构造函数和原型对象之间的关系汇成的了一条链。原型链诞生了!
原型链:
作者为了解决js中的继承问题,于是就设计了原型链。画图表示如下:
通过原型链我们可以访问到实例对象上原本没有的方法,例如:toString、hasOwnProperty、valueOf等,
举栗子:
实例对象找方法,先从自身找,找不到的话就顺着原型链去原型对象找,原型对象找不到的话就去原型的原型里找,一直到Object为止。
例子:
JavaScript中的对象,都有一个内置属性[Prototype],指向这个对象的原型对象。当查找一个属性或方法时,如果在当前对象中找不到,会继续在当前对象的原型对象中查找;如果原型对象中依然没有找到,会继续在原型对象的原型中查找(原型也是对象,也有它自己的原型);直到找到为止,或者查找到最顶层的原型对象中也没有找到,就结束查找,返回undefined。这个查找过程是一个链式的查找,每个对象都有一个到它自身原型对象的链接,这些链接组建的整个链条就是原型链。拥有相同原型的多个对象,他们的共同特征正是通过这种查找模式体现出来的。
在上面的查找过程,我们提到了最顶层的原型对象,这个对象就是Object.prototype,这个对象中保存了最常用的方法,如toString、valueOf、hasOwnProperty等,因此我们才能在任何对象中使用这些方法。
大致总结一下就是:
1、Object是作为众多new出来的实例的基类 function Object(){ [ native code ] }
2、Function是作为众多function出来的函数的基类 function Function(){ [ native code ] }
3、构造函数的proto(包括Function.prototype和Object.prototype)都指向Function.prototype
4、原型对象的proto都指向Object.prototype
5、Object.prototype.proto指向null