创作者: 后端二牛
承继是程序词汇词汇中两个最人称道的基本概念。很多程序词汇词汇都全力支持三种承继形式:USB承继和同时实现承继。USB承继只承继形式亲笔签名,而同时实现承继则承继前述的形式。在ECMAScript中,表达式没亲笔签名,难以同时实现USB承继,只全力支持同时实现承继,承继主要就倚靠的是蓝本链。
先上看两个单纯的蓝本链承继实例,如下表所示图:
具体来说新闻稿两个 Human表达式,给它的蓝本加进两个 getHumanSex形式。接着新闻稿两个 Person表达式,要让 Person承继 Human,能采用 Human的特性和形式,如果把 Person的蓝本再次表达式为 Human的两个实例就好了。最终给 Person的蓝本(也是 Human的那个实例)加进两个 getPersonSex形式。那时建立 Person的两个实例 personObj, name=李四,age=12。假如出访 personObj.name,所以就能间接出访到是 李四了。倘若那时要出访 humanSex,即使 personObj中没,因此会顺著 __proto__特性到 Person的蓝本中去找,而 Person的蓝本是 Human的两个实例,它的 humanSex特性是 男/女,因此 personObj.humanSex的值是 男/女,这就达至了承继的效用。倘若要出访 getPersonSex, personObj中没,也是到蓝本中去找,找出了就初始化,即使是采用 personObj.getPersonSex,因此在形式 getPersonSex中, this指的是 personObj, returnthis.personSex是回到 personObj.personSex,即为 男。 假如是初始化 personObj.getHumanSex,却是先顺著 __proto__到 Person的蓝本中去找, Person的蓝本是 Human的两个实例,里头没,那咋办呢,即使该蓝本是 Human的两个实例,因此它大自然也会有个 __proto__对准 Human的蓝本,只好就竭尽全力顺著那个 __proto__到 Human的蓝本中去找,这是简而言之的蓝本链,找出了就已经开始初始化,大自然 getHumanSex中的 this指的也是 personObj, returnthis.humanSex是 returnpersonObj.humanSex,即 男/女。这是蓝本链承继。
细心的读者也许会发现,在 Human的蓝本中也有个 __proto__,所以 Human的蓝本会不会也是某个表达式的两个实例呢?假如我们初始化 personObj.toString(),所以我们初始化的究竟是谁的 toString()呢?要回答那个问题,我们上看下面这幅示意图:
Human的蓝本其实是 Object的两个实例,大自然 __proto__对准的是 Object的蓝本,而 toString是 Object蓝本上的形式。
其实ECMAScript中所有引用类型的默认蓝本都是 Object的实例,也是说所有引用类型默认都承继了 Object,而那个承继正是通过蓝本链同时实现的。
蓝本的好处是所有的实例能共享它所包含的特性和形式,也是说不必在构造表达式中定义对象实例的信息,但正如JavaScript建立对象(三)——蓝本模式中所说,这也带来了两个问题。蓝本特性会被所有实例共享,对于引用类型会出现一些应用时的共享问题,因此需要在构造函中,而不是在蓝本对象中定义特性。但是在通过蓝本来同时实现承继时,蓝本前述上是另两个表达式的实例。只好,原来的实例特性也就顺理成章地变成了那时的蓝本特性了,所以蓝本共享数据的问题又出现了。
另外两个问题是,建立子类型的实例时,没法向超类型的构造表达式中传递参数。前述上,应该说是没办法在不影响所有对象的实例下,给超类型的构造表达式传递参数。有鉴于此,实践中很少会单独采用蓝本链。