前言:
现在咱们对“javascript 原型 原型链”大体比较看重,我们都需要剖析一些“javascript 原型 原型链”的相关资讯。那么小编在网上汇集了一些有关“javascript 原型 原型链””的相关内容,希望各位老铁们能喜欢,兄弟们一起来学习一下吧!原创: 前端二牛
继承是面向对象语言中一个最为人津津乐道的概念。许多面向对象语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。在ECMAScript中,函数没有签名,无法实现接口继承,只支持实现继承,继承主要依靠的是原型链。
先来看一个简单的原型链继承示例,如下图:
首先声明一个 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创建对象(三)——原型模式中所说,这也带来了一个问题。原型属性会被所有实例共享,对于引用类型会出现一些应用时的共享问题,所以需要在构造函中,而不是在原型对象中定义属性。但是在通过原型来实现继承时,原型实际上就是另一个函数的实例。于是,原来的实例属性也就顺理成章地变成了现在的原型属性了,那么原型共享数据的问题又出现了。
另外一个问题是,创建子类型的实例时,没法向超类型的构造函数中传递参数。实际上,应该说是没办法在不影响所有对象的实例下,给超类型的构造函数传递参数。有鉴于此,实践中很少会单独使用原型链。
标签: #javascript 原型 原型链