用小猪佩奇说明Javascript的原型和原型链

  没错,我就是标题党!你已经成功被我骗进来了。来都来了,那就聊聊再走呗!接下来就听我一本正经地跟你说道说道。javascript

  Javascript的原型是这门语言的一个重点和难点。看过不少大佬写的解释Javascript原型的文章,可是不少对于初学者其实不是很友好,看完以后仍是云里雾里。我虽然不敢说能把这个东西解释的很清楚,可是做为一个前端菜鸟,我可能更知道你们在读文章的时候会卡在哪一步,因此但愿本文可以帮助到你们。前端

  在文章开始,我先明确几个概念,这里若是你以为很差理解,就先紧紧地记住它,而后继续往下阅读,读完你就会豁然开朗,相信我!另外,必定要每行每字去读,勿跳着读,博主就犯过这样的错误,致使越读越糊涂,我这里也尽可能压缩字数,保证你读的每一个字都是有用的。答:“你都忽悠半天了赶忙开始吧!”java

  • prototype :每一个函数都会有这个属性,这里强调,是函数,普通对象是没有这个属性的(这里为何说普通对象呢,由于JS里面,一切皆为对象,因此这里的普通对象不包括函数对象)。它是构造函数的原型对象;
  • __proto__ :每一个对象都有这个属性,,这里强调,是对象,一样,由于函数也是对象,因此函数也有这个属性。它指向构造函数的原型对象;
  • constructor :这是原型对象上的一个指向构造函数的属性。

先看代码函数

// Pig的构造函数
function Pig(name, age) {
    this.name = name;
    this.age = age;
}
// 建立一个Pig的实例,小猪佩奇
var Peppa = new Pig('Peppa', 5);

敲黑板,划重点,理解这一句整个问题的关键,请多重复几遍。:在实例化的时候,prototype上的属性会做为原型对象赋值给实例。 也就是说小猪佩奇的原型,就是从Pig.prototype继承来的写成代码就是这个样子Peppa.__proto__ === Pig.prototype

Pig是一个函数对象,它是Function对象的一个实例,因此Pig.__proto__ === Function.prototype必定为true。this


咱们在上面提到了constructor这个属性,它位于原型对象上而且指向构造函数,因此Pig.prototype.constructor === Pigspa


至此,我大体捋了一遍这三个属性的关系,咱们再顺着这条链继续往深挖一挖。Function.prototype,也就是Function的原型对象。这个原型对象的__proto__指向了Object.prototype。打破砂锅问到底,Object.prototype.__proto__又指向谁,JS世界里万物皆对象,Object彷佛已经到了原型链的顶端,果真不出我所料,它确实是null。:prototype


你可能要吐槽了,说好的讲明白呢,这一坨都被你绕糊涂了,一张图赛过千言万语:code

解释一下上面的图。先看蓝色那条线,Pig,Function和Object的构造函数是Function的实例,因此它们的__proto__均指向Function.prototype。这就印证了敲黑板说的那句话,prototype属性会做为原型对象赋值给实例,每一个对象的__proto__都指向原型对象(处于最顶层的Object.prototype除外)。对象

再看绿色那条,Pig和Function的原型对象是Object的实例,因此它们的__proto__均指向了Object.prototype,也就是Object的原型对象。继承

浅蓝色的线代表了原型的constructor指向了构造函数。

Emmmm,其实也没那么复杂对不对?接着说一下原型链。正如你在上面图中所看到的,JS在建立对象的时候,会在新对象上产生一个__proto__的属性,这个属性指向了它构造函数的原型的prototype。由此一级一级向上直到到达Object.prototype.__proto__ === null的这个链条咱们称之为原型链。

关于继承的概念,原本想写在一块儿的,后来想一想,内容过多只会让文章成为收藏不看系列,因此这块的内容放在之后的文章里详解。各位看官,我想我大体讲明白了原型和原型链的概念,有什么错误还恳请批评指正。

相关文章
相关标签/搜索