一篇文章让你搞懂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 相关文章推荐
jQuery 选择表格(table)里的行和列及改变简单样式
Dec 15 Javascript
javascript错误的认识不用关心内存管理
Dec 15 Javascript
jQuery中attr()方法用法实例
Jan 05 Javascript
Javascript代码实现仿实例化类
Apr 03 Javascript
JavaScript数组前面插入元素的方法
Apr 06 Javascript
基于Two.js实现星球环绕动画效果的示例
Nov 06 Javascript
(模仿京东用户注册)用JQuery实现简单表单验证,初学者必看
Jan 08 jQuery
JavaScript文本特效实例小结【3个示例】
Dec 22 Javascript
微信小程序五子棋游戏的悔棋实现方法【附demo源码下载】
Feb 20 Javascript
通过实例学习React中事件节流防抖
Jun 17 Javascript
js 计算月/周的第一天和最后一天代码
Feb 01 Javascript
Vue看了就会的8个小技巧
Jan 21 Vue.js
微信小程序实现锚点跳转
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 csv操作类代码
2009/12/14 PHP
8个出色的WordPress SEO插件收集
2011/02/26 PHP
解析PHP函数array_flip()在重复数组元素删除中的作用
2013/06/27 PHP
php旋转图片90度的方法
2013/11/07 PHP
php版微信公众平台接口参数调试实现判断用户行为的方法
2016/09/23 PHP
thinkphp中的多表关联查询的实例详解
2017/10/12 PHP
PHP使用HTML5 FormData对象提交表单操作示例
2019/07/02 PHP
js报错 Object doesn't support this property or method的原因分析
2011/03/31 Javascript
JQuery扩展插件Validate 3通过参数设置错误信息
2011/09/05 Javascript
js日期时间补零的小例子
2013/03/05 Javascript
固定背景实现的背景滚动特效示例分享
2013/05/19 Javascript
javascript中new关键字详解
2015/12/14 Javascript
Node.js学习之TCP/IP数据通讯(实例讲解)
2017/10/11 Javascript
详解webpack打包时排除其中一个css、js文件或单独打包一个css、js文件(两种方法)
2018/10/26 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
2020/02/09 Javascript
[04:56]经典回顾:前Ehome 与 前LGD
2015/02/26 DOTA
Python SMTP发送邮件遇到的一些问题及解决办法
2018/10/24 Python
python web框架Flask实现图形验证码及验证码的动态刷新实例
2019/10/14 Python
在TensorFlow中屏蔽warning的方式
2020/02/04 Python
python代码实现将列表中重复元素之间的内容全部滤除
2020/05/22 Python
Django限制API访问频率常用方法解析
2020/10/12 Python
如何让PyQt5中QWebEngineView与JavaScript交互
2020/10/21 Python
python 匿名函数与三元运算学习笔记
2020/10/23 Python
详解matplotlib中pyplot和面向对象两种绘图模式之间的关系
2021/01/22 Python
购买瑞典当代设计的腕表和太阳眼镜:TRIWA
2016/10/30 全球购物
选购国际女性时装设计师品牌:IFCHIC(支持中文)
2018/04/12 全球购物
CHRONEXT英国:您的首选奢华腕表目的地
2020/03/30 全球购物
应届生幼儿园求职信
2013/11/12 职场文书
大学生创业计划书的格式要求
2013/12/29 职场文书
城管综合整治方案
2014/05/01 职场文书
企业党员一句话承诺
2014/05/30 职场文书
2015年人力资源部工作总结
2015/04/30 职场文书
教师正风肃纪心得体会
2016/01/15 职场文书
2016教师学习教育法心得体会
2016/01/19 职场文书
Python机器学习之KNN近邻算法
2021/05/14 Python
CSS中Single Div 绘图技巧的实现
2021/06/18 HTML / CSS