一篇文章让你搞懂JavaScript 原型和原型链


Posted in Javascript onNovember 23, 2020

本文由葡萄城技术团队原创并首发

转载请注明出处:葡萄城官网

与多数面向对象的开发语言有所不同,虽然JavaScript没有引入类似类的概念(ES6已经引入了class语法糖),但它仍然能够大量的使用对象,那么如何将所有对象联系起来就成了问题。于是就有了本文中我们要讲到的原型和原型链的概念。

原型和原型链作为深入学习JavaScript最重要的概念之一,如果掌握它了后,弄清楚例如:JavaScript的继承,new关键字的原来、封装及优化等概念将变得不在话下,那么下面我们开始关于原型和原型链的介绍。

什么是原型?

JS中的对象包含了一个prototype的内部属性,这个属性所对应的就是该对象的原型。

我们先看下图:a、b、c 分别为数组、对象、函数。

一篇文章让你搞懂JavaScript 原型和原型链

可以看到,三者都有一个属性:__proto__

一篇文章让你搞懂JavaScript 原型和原型链

这个 __proto__ 称作 隐式原型。

除此之外,c还有一个属性:prototype

一篇文章让你搞懂JavaScript 原型和原型链

这个prototype 称作 显式原型。

小结一下:

  • 所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型)
  • 所有函数除了有_proto_属性之外还拥有prototype属性(显式原型)
  • 原型对象:每创建一个函数,该函数会自动带有一个prototype属性,该属性是一个指针,指向了一个对象,我们称之为原型对象。

函数除了有_proto_属性之外还拥有prototype属性,我们借助构造函数来寻找二者之间的关系。如下图:

一篇文章让你搞懂JavaScript 原型和原型链

一篇文章让你搞懂JavaScript 原型和原型链

总结如下(结合上图更容易理解):

1. 实例对象a只有__proto__(隐式原型),构造函数既有 __proto__(隐式原型)也有prototype(显式原型)

2. __proto__ 和 prototype 都是一个对象,既然是对象,就表示他们也有一个 __proto__

a.__proto__.__proto__
A.prototype.__proto__

3.实例对象a的隐式原型指向它构造函数的显式原型,指向的意思是恒等于

a.__proto__ === A.prototype

4. 当调用某种方法或查找某种属性时,首先会在自身调用和查找,如果自身并没有该属性或方法,则会去它的__proto__属性中调用查找,也就是它构造函数的prototype中调用查找。

什么是原型链?

先看下图,提出一个问题:

1. 在 Object的显式原型添加属性b,为什么 示例对象p 能使用此属性呢? p.b = b

2. 为什么 p.a 为undefined

一篇文章让你搞懂JavaScript 原型和原型链

如下图所示

1.    实例对象p的隐式原型(__proto__)是一个对象,有两个属性值:constructor 和 __proto__

2.   p.__proto__.constructor 返回的结果为构造函数Person

3.   p.__proto__.__proto__ .constructor 返回的结果为Object()函数

一篇文章让你搞懂JavaScript 原型和原型链

结合上面所讲的显式原型与隐式原型之间的关系,等同如下:

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

一篇文章让你搞懂JavaScript 原型和原型链

什么是原型继承?

Person.prototype 只是一个指针,指向的是原型对象,但是这个原型对象并不特别,它也只是一个普通对象。假设说,这时候,我们让 Person.prototype 不再指向最初的原型对象,而是另一个类 (Animal)的实例,情况会怎样呢?

一篇文章让你搞懂JavaScript 原型和原型链

执行该代码   Person.prototype = new Animal() 后,Person的prototype指针指向发生了变化,指向了一个 Animal 实例。

当 p 去访问 address 属性时,js会先在 p 的实例属性中查找,发现找不到后,就会去 Person 的原型对象上 查找。因为Person的原型对象已经被我们换成一个animal实例,所以就会先找animal实例的属性,当发现还是没有 address属性,就会去Animal的原型对象上查找,最终找到。

这就说明,我们可以通过原型链的方式,实现 Person 继承 Animal 的所有属性和方法。

结语

看到这,相信大家对原型和原型链的概念应该已经有了一定了解了,如果仍然不太理解,也不用气馁,因为闭包及原型链是JavaScript最难理解的几部分。相信之后在不断的开发实践中会使你理解的更为透彻,多学习多思考才能更快掌握。如果大家有任何反馈和问题,也欢迎通过评论区告诉我,谢谢。

以上就是一篇文章让你搞懂JavaScript 原型和原型链的详细内容,更多关于JavaScript 原型和原型链的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
JS获取DropDownList的value值与text值的示例代码
Jan 07 Javascript
jQuery中slideUp 和 slideDown 的点击事件
Feb 26 Javascript
javascript实现的固定位置悬浮窗口实例
Apr 30 Javascript
JavaScript编写简单的计算器
Nov 25 Javascript
基于JavaScript实现简单的随机抽奖小程序
Jan 05 Javascript
JavaScript遍历求解数独问题的主要思路小结
Jun 12 Javascript
easyui combotree加载静态数据问题(选不上)解决方法
Dec 26 Javascript
Ionic+AngularJS实现登录和注册带验证功能
Feb 09 Javascript
Bootstrap风格的zTree右键菜单
Feb 17 Javascript
vue实现密码显示与隐藏按钮的自定义组件功能
Apr 23 Javascript
使用element-ui的el-menu导航选中后刷新页面保持当前选中状态
Jul 19 Javascript
VUE实现图片验证码功能
Nov 18 Javascript
微信小程序实现锚点跳转
Nov 23 #Javascript
javascript实现电商放大镜效果
Nov 23 #Javascript
用webAPI实现图片放大镜效果
Nov 23 #Javascript
Vue 的 v-model用法实例
Nov 23 #Vue.js
JavaScript实现网页留言板功能
Nov 23 #Javascript
VUE+Element实现增删改查的示例源码
Nov 23 #Vue.js
js观察者模式的弹幕案例
Nov 23 #Javascript
You might like
如何在PHP中使用Oracle数据库(5)
2006/10/09 PHP
php检测apache mod_rewrite模块是否安装的方法
2015/03/14 PHP
详解PHP原生DOM对象操作XML的方法
2016/10/17 PHP
Ubuntu 16.04下安装PHP 7过程详解
2017/03/28 PHP
php实现微信企业转账功能
2018/10/02 PHP
PHP面向对象程序设计之构造方法和析构方法详解
2019/06/13 PHP
Yii 实现数据加密和解密
2021/03/09 PHP
JavaScript 比较时间大小的代码
2010/04/24 Javascript
jQuery-ui中自动完成实现方法
2010/06/10 Javascript
原生JavaScript编写俄罗斯方块
2015/03/30 Javascript
javascript实现设置、获取和删除Cookie的方法
2015/06/01 Javascript
nodejs初步体验篇
2015/11/23 NodeJs
微信小程序 swiper制作tab切换实现附源码
2017/01/21 Javascript
vue-resourse将json数据输出实例
2017/03/08 Javascript
详谈js遍历集合(Array,Map,Set)
2017/04/06 Javascript
JavaScript模拟文件拖选框样式v1.0的实例
2017/08/04 Javascript
JavaScript文件的同步和异步加载的实现代码
2017/08/19 Javascript
让axios发送表单请求形式的键值对post数据的实例
2018/08/11 Javascript
解决layui前端框架 form表单,table表等内置控件不显示的问题
2018/08/19 Javascript
React中使用外部样式的3种方式(小结)
2019/05/28 Javascript
NodeJS 文件夹拷贝以及删除功能
2019/09/03 NodeJs
如何在Vue中抽离接口配置文件
2019/10/31 Javascript
[02:31]2018年度DOTA2最具人气选手-完美盛典
2018/12/16 DOTA
python中的lambda表达式用法详解
2016/06/22 Python
用python制作游戏外挂
2018/01/04 Python
Python实现判断字符串中包含某个字符的判断函数示例
2018/01/08 Python
Python中str.join()简单用法示例
2018/03/20 Python
从0开始的Python学习016异常
2019/04/08 Python
TensorFlow tensor的拼接实例
2020/01/19 Python
IE矩阵Matrix滤镜旋转与缩放及如何结合transform
2012/11/29 HTML / CSS
H5 video poster属性设置视频封面的方法
2020/05/25 HTML / CSS
一套软件开发工程师笔试题
2015/05/18 面试题
村官学习十八大感想
2014/01/15 职场文书
数控专业大学毕业生职业规划范文
2014/02/06 职场文书
蓝颜请假条
2014/04/11 职场文书
记者节感言
2015/08/03 职场文书