我们先使用构造函数创建一个对象
function Peson() {}
const peson = new Peson();
peson.name = 'FC';
console.log(peson.name) //FC
简单把,接下来进入正文:
每个函数都有个prototype,在平常经常可以看到,例如:
function Peson() {}
const peson1 = new Peson();
const peson2 = new Peson();
Peson.prototype.name = 'FC';
console.log(peson1.name,'name') //FC
console.log(peson1.name,'name') //FC
prototype这个属性到底指的是什么呢?
其实javaScript每一个对象创建(创建创建创建)的时候(null除外)都会与另一个对象关联,也就是我们所说的原型,继承该原型的属性和方法.
函数就是通过prototype这个属性与原型关联,如图:
那么构造函数的实例跟原型之间又有什么关系呢? 接下来介绍第二个属性_proto_
javaScript对象上都有_proto_这个属性,它会指向这个对象的原型:
function Peson() {}
const peson = new Peson();
console.log(peson._proto_ === Peson.prototype) //true
更新关系图:
既然实例和构造函数都有属性指向原型,那么原型是否能指向实例和构造函数呢?这就有第三个属性了constructor:因为实例有多个的原因,不指向实例,每个原型上都有个constructor属性指向与之关联的构造函数
const peson = new Peson();
console.log(peson === Peson.prototype.constructor) //true
再更新关系图:
了解了实例,构造函数,原型的关系 ,接下来就讲讲实例和原型的关系
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。
例如:
function Peson() {}
const peson = new Peson();
Peson.prototype.name = 'FC';
peson.name = 'CF';
console.log(peson.name) // CF
delete peson.name
console.log(peson.name) // FC
看这个例子,当给peson添加name属性时,打印的值为CF,当我们删除这个属性的时候,打印的则为FC,所以从peson上没找到的属性就会从peson的原型上也就是peson._proto_上面找.
但是peson的原型上也没找到呢?原型的原型是什么?
js万物皆可对象,原型也是个对象,上面也说过对象都会与另一个对象关联,通过_proto_指向原型:
所以关系如图:
Object.prototype作为一个原型是不是应该也会有constructor和prototype属性指向与被指向呢?
这里我们用最原始的方式创建一个对象
const obj = new Object();
所以我们把 所有的关系串联,如图:
那对象原型的上面指向什么呢?
这里打印一下 console.log(obj._proto_._proto_) || console.log(Object.prototype._proto_) // null
即Object.prototype上是没有原型的 为null 所以查找到对象原型时就可以不用往上找了
所以整个实例,原型,构造函数的关系,如图:
这些原型用_proto_关联的这个链路,称为原型链(紫色)