回顾:上一篇讲了原型对象与prototype和__proto__(传送门 )三者之间的关系
三:constructor
constructor [kənˈstrʌktə(r)] :构造器, 这是子类的__ptoto__对象和父类的prototype对象的一个属性,它通常指向父类本身
function Fn() { this.n = 20 } Fn.prototype.sing = function() { console.log(this.n) } var deb = new Fn() console.log(deb.__proto__.constructor === Fn) //true console.log(Fn.prototype.constructor === Fn) // true
这也进一步证明了 ,子类的__ptoto__对象全等于父类的prototype对象!
到现在,我们已经可以画出一个父类,子类,与prototype三者的关系图
上图是学习原型链的基础。
在这张图中:
prototype对象 :prototype是父类的一个属性,由于它的值是一个对象类型,因而它既可以看作是父类的属性,也可以认为是父类的一个隐式的对象,所有的函数都有一个prototype对象 !
原型对象有一个constructor属性,它指向了父函数本身。父函数也可以通过自身的prototype属性找到这个原型对象;由这个父级实例的对象也可以通过__proto__属性
找到这个原型对象。
父级:由于父级是一个构造函数,它使用new关键字实例了子类,因而我们可以认为,父级使用new关键字和子类产生了联系。同时,子类也可以通过__proto__对象的constructor找到自身的父级,这是
由于自身的__proto__就是父级的prototype对象,本质上 是先通过__proto__属性找到父级的prototype对象,再通过prototype对象的constructor指向找到 其父级
__proto__: 结合上一篇,__proto__属性隐式存在于每一个obj对象身上,而prototype的值也是对象类型,这也说明,任何父类的prototype对象也都有一个__proto__属性!
子类的__proto__其实就是一条锁链,指向其父类的prototype对象,我们也可以得出一条结论:所有对象的__proto__都指向它的父类的prototype对象!
基于constructor,我们通过在原型对象的__proto__对象的constructor属性指向可以得知,原型对象的__proto__指向了Object.prototype .
(Object对象是所有对象的共有父类,而对象的__proto__属性则指向它的构造函数的prototype对象!)
console.log(deb.__proto__.__proto__ === Object.prototype) //true
这句话的理解是:“对象的原型对象的原型对象是Object的原型吗”
举个栗子:
小明有爸爸妈妈,也有爷爷奶奶和外公外婆,有天他问妈妈:” 你的妈妈的妈妈是谁?“,妈妈指着外婆,告诉他:”我的妈妈是xxx,她是你的外婆“,然后小明的妈妈问外婆:”我的妈妈的妈妈是谁呢?“
外婆指着天空说:” 我没有妈妈.“
在这个例子里,假设所有人都有一个纽带(__proto__),用于指明自己的亲人,小明是一个对象(son),他用自己的纽带(son.__proto__)找到了自己的妈妈(son.__proto__),也就是prototype,
然后他想知道自己的 外婆是谁,他的妈妈通过用自己的纽带(prototype.__proto__)告诉他,他的外婆是xxx(Object.prototype),然后妈妈也想知道自己的外婆(prototype.proto.proto)是谁,外婆通过自己的纽带 (Object.prototype.__proto__)想回答这个问题,可是没找到,于是告诉妈妈,什么都没有(null)
这虽是个简单的例子,却深刻说明了一个原理:
1.所有的对象都有一个__proto__属性,这个属性指向了自己父级的原型对象,
2.Object对象是所有对象的共有父类
3.Object对象的原型对象的__proto__是null
图解:
这种通过原型链方式将原型对象与对象之间链接的 关系我们就叫做原型链。
以上。