进修JavaScript之原型链

原型链之前一向都不是很邃晓,这两天把《你不知道的JavaScript》和《JavaScript高等程序设计》的原型链那章看完后有所邃晓,在这里先记下来,加深印象。

什么是原型对象

要讲清晰什么是原型链需要从原型对象最先谈,那末什么是原型对象呢?《JavaScript高等程序设计》中是如许讲的:

不管什么时候,只需建立了一个新函数,就会依据一组特定的规则为该函数建立一个prototype属性,这个属性指向函数的原型对象。

简朴来讲,原型对象也是对象,然则经由历程原型对象能够完成对象的属性继承。
这里用《JavaScript高等程序设计》这本书上的demo来诠释一下:

function Person () {
}

Person.prototype.name = 'Nicholas'
Person.prototype.age = 29
Person.prototype.job = 'Software Engineer'
Person.prototype.sayName = function () {
  console.log(this.name)
}

var person1 = new Person()

var person2 = new Person()

这里声清楚明了一个Person函数,没有定义任何属性;然则在Person的原型对象里定义了name,age,job属性和sayName要领。以后建立了两个Person的实例对象,person1和person2。在这里组织函数,原型对象,实例对象三者的关联用一张图片示意就是《进修JavaScript之原型链》
(图片泉源谷歌,侵删)

如图所示,Person的prototype指针指向它的原型对象,实例对象的[[Prototype]]指针也指向它的原型对象。这里简朴申明一下什么是[[Prototype]]指针:

挪用组织函数建立一个新实例以后,该实例的内部将包括一个指针(内部属性),指向组织函数的原型对象,这就是[[Prototype]]指针。

如今,person1和person2的[[Prototype]]都指向了Person.prototype,如许的话Person.prototype里的要领和属性是被person1和person2共用的。

怎样证实他们共用Person.prototype内里的属性和要领?请实行下面的语句:

person1.sayName() // 'Nicholas'
person2.sayName() // 'Nicholas'

有人说了,你这初始化的name属性只要一个,实行的效果固然都一样啊。那末请再尝尝下面这句:

console.log(person1.sayName === person2.sayName) //true

效果很明显,person1.sayName和person2.sayName指向的是同一个要领。到这里能够有人会迷惑:一最先的代码中Person函数里并没有定义任何属性和要领,为何person1和person2能实行sayName要领?那末这就要来谈谈对象属性挪用的历程了。

以上面代码为例,当你实行person1.name时,解析器会最先查找person1中有没有name属性,假如找到了则返回属性值;假如没找到,则在person1的原型对象中继承找,找到了则返回属性值;假如还没找到,就沿着原型链往上继承找,假如终究照样没找到就返回undefined。

到这里人人也邃晓了多个对象实例同享原型对象的属性和要领的基础原理了,那末有人又会问了,假如我经由历程给实例对象属性赋值能不能重写原型对象里的属性和要领呢?

答案是不可的,在实例对象中对原型对象中的同名属性赋值会屏障原型对象中的属性。简朴诠释就是,对person1中的name属性赋值会直接在person1中增加name属性。然则有两种情况下,当name属性不存在于person1中而存在于原型对象中时,直接给person1.name赋值会有不一样事变发作:
1.当原型对象中的name属性标记为只读(writable: false)时,对name属性的赋值不会在person1增加name属性,也不会修正原型对象中的name属性,在严厉形式下还会报错。
2.当原型对象中的name属性是一个setter,那末对person1中的name属性实行赋值语句就会挪用setter,但name不会被增加到person1中。
这部份假如不懂什么是只读和setter,人人能够去看一下Object.defineProperty

什么是原型链

实在讲到这里,原型对象是什么已基础清晰了。那末原型链就很简朴了,继承上面的demo:

function Parent () {
  this.parentName = 'noOne'
}

function Person () {
  this.name = 'Nicholas'
}

Person.prototype = new Parent()

var person1 = new Person()

这个例子中,我们把Parent的实例对象赋给了Person的原型对象。Person.prototype中的[[Prototype]]此时指向了Parent.prototype。闻一知十,Parent.prototype也能够是另一个原型的实例对象,如许不停地层层递进便构成了原型链。

原型链的重要作用就是完成继承,这部份后续的文章我会继承讲。

本人履历尚浅,现在关于前端仍在不停探索和进修,文章若有毛病,迎接列位斧正。末了附上本人博客地址和原文链接,希望能向列位多多进修。

lbj的前端之路
原文链接:进修JavaScript之原型链

    原文作者:LiuBoJun
    原文地址: https://segmentfault.com/a/1190000009369920
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞