时间:2021-05-25
本文由葡萄城技术团队原创并首发
转载请注明出处:葡萄城官网
与多数面向对象的开发语言有所不同,虽然JavaScript没有引入类似类的概念(ES6已经引入了class语法糖),但它仍然能够大量的使用对象,那么如何将所有对象联系起来就成了问题。于是就有了本文中我们要讲到的原型和原型链的概念。
原型和原型链作为深入学习JavaScript最重要的概念之一,如果掌握它了后,弄清楚例如:JavaScript的继承,new关键字的原来、封装及优化等概念将变得不在话下,那么下面我们开始关于原型和原型链的介绍。
什么是原型?
JS中的对象包含了一个prototype的内部属性,这个属性所对应的就是该对象的原型。
我们先看下图:a、b、c 分别为数组、对象、函数。
可以看到,三者都有一个属性:__proto__
这个 __proto__ 称作 隐式原型。
除此之外,c还有一个属性:prototype
这个prototype 称作 显式原型。
小结一下:
函数除了有_proto_属性之外还拥有prototype属性,我们借助构造函数来寻找二者之间的关系。如下图:
总结如下(结合上图更容易理解):
1. 实例对象a只有__proto__(隐式原型),构造函数既有 __proto__(隐式原型)也有prototype(显式原型)
2. __proto__ 和 prototype 都是一个对象,既然是对象,就表示他们也有一个 __proto__
a.__proto__.__proto__A.prototype.__proto__3.实例对象a的隐式原型指向它构造函数的显式原型,指向的意思是恒等于
a.__proto__ === A.prototype4. 当调用某种方法或查找某种属性时,首先会在自身调用和查找,如果自身并没有该属性或方法,则会去它的__proto__属性中调用查找,也就是它构造函数的prototype中调用查找。
什么是原型链?
先看下图,提出一个问题:
1. 在 Object的显式原型添加属性b,为什么 示例对象p 能使用此属性呢? p.b = b
2. 为什么 p.a 为undefined
如下图所示
1. 实例对象p的隐式原型(__proto__)是一个对象,有两个属性值:constructor 和 __proto__
2. p.__proto__.constructor 返回的结果为构造函数Person
3. p.__proto__.__proto__ .constructor 返回的结果为Object()函数
结合上面所讲的显式原型与隐式原型之间的关系,等同如下:
p.__proto__.__proto__ = Object.prototype
所以p.b打印结果为b,p没有b属性,会一直通过__proto__向上查找,最后当查找到Object.prototype时找到,最后打印出b,向上查找过程中,得到的是Object.prototype,而不是Function.prototype,找不到a属性,所以结果为undefined,这就是 原型链,通过__proto__向上进行查找,最终到null结束。
总结:
1. 查找属性,如果本身没有,则会去__proto__中查找,也就是构造函数的显式原型中查找,如果构造函数的显式原型中也没有该属性,因为构造函数的显式原型也是对象,也有__proto__,那么会去它的显式原型中查找,一直到null,如果没有则返回undefined
2. p.__proto__.constructor == function Person(){}
3. p.___proto__.__proto__== Object.prototype
4. p.___proto__.__proto__.__proto__== Object.prototype.__proto__ == null
5. 通过__proto__形成原型链而非protrotype
什么是原型继承?
Person.prototype 只是一个指针,指向的是原型对象,但是这个原型对象并不特别,它也只是一个普通对象。假设说,这时候,我们让 Person.prototype 不再指向最初的原型对象,而是另一个类 (Animal)的实例,情况会怎样呢?
执行该代码 Person.prototype = new Animal() 后,Person的prototype指针指向发生了变化,指向了一个 Animal 实例。
当 p 去访问 address 属性时,js会先在 p 的实例属性中查找,发现找不到后,就会去 Person 的原型对象上 查找。因为Person的原型对象已经被我们换成一个animal实例,所以就会先找animal实例的属性,当发现还是没有 address属性,就会去Animal的原型对象上查找,最终找到。
这就说明,我们可以通过原型链的方式,实现 Person 继承 Animal 的所有属性和方法。
结语
看到这,相信大家对原型和原型链的概念应该已经有了一定了解了,如果仍然不太理解,也不用气馁,因为闭包及原型链是JavaScript最难理解的几部分。相信之后在不断的开发实践中会使你理解的更为透彻,多学习多思考才能更快掌握。如果大家有任何反馈和问题,也欢迎通过评论区告诉我,谢谢。
以上就是一篇文章让你搞懂JavaScript 原型和原型链的详细内容,更多关于JavaScript 原型和原型链的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
继承是面向对象编程中又一非常重要的概念,JavaScript支持实现继承,不支持接口继承,实现继承主要依靠原型链来实现的。原型链首先得要明白什么是原型链,在一篇
这篇文章主要介绍了JavaScript原型继承和原型链原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
一个例子让你彻底明白原型对象和原型链开篇之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述
在上篇文章给大家介绍了《谈谈我对JavaScript原型和闭包系列理解(随手笔记6)》,谈谈我对JavaScript原型和闭包系列理解(随手笔记9)可以点击了解
整理《javascript高级程序设计》中继承的方法以及优缺点。1.原型链ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法。原型链继承