咱们先看一个例子:
var a=new Date();
a.__proto__===Date.prototype //true
a.constructor===Date //true
//所以可得
a.constructor.prototype===Date.prototype //true
从上面的例子我们就可以清晰看出对象和函数的关系。简单理解:每次new都可以看做一次构造,new的函数就是构造函数,new之后的函数就是被构造的函数,由于他被构造,所以他的隐式原型链_proto_就是他的构造函数的显式原型。
形象化就是这个意思:上例的Date是父亲,new就是一个创造的过程,他创造出a这个儿子。constructor可以理解为谁创造了他,所以a.constructor===Date。父亲有很多财产,他的财产就是prototype,a没有财产,但是默认a会继承父亲的财产,由于这个继承不是明显的,所以就是隐式原型_proto_。a赚钱了,他要给父亲用,但是在显式原型链上只有父亲给儿子东西没有儿子给父亲的道理,这个时候就需要用隐式原型链,儿子可以通过使用a._proto_.fangfa=function(){}的方式给父亲“尽孝”,但是并不推荐这样做,因为这样会间接性给其他兄弟这份“财产”,当然如果是独生子的话我无话可说。
当a被实例化的时候,他会继承父类的constructor。这个constructor就是继承的父类本身,函数的_proto_就是父类的prototype。
prototype是函数的原型对象,他又有_proto_和constructor,他的constructor指向父类函数,他的_proto_指向父类函数的prototype原型对象。
任何子类如果要用a._proto_.fangfa=function(){}来创建一个函数方法的时候,都会默认给父类创建一个方法。所以咱们如果是子类私有的方法就要避免这样写。直接a.fangfa=function(){}。
constructor是对象指向函数,这个函数可能是继承来的,也有可能是自己本来就有的。但是他们的终点都是Function,这里要理解,Function它不只是一个函数,还是一个对象,所以Function的constructor是指向了它本身。
这里的知识很复杂,但是一个图就可以直观看出来。链接:https://blog.csdn.net/cc18868876837/article/details/81211729
使用实例的__proto__
属性改写原型,必须相当谨慎,不推荐使用,因为这会改变“类”的原始定义,影响到所有实例。