一篇文章让你搞懂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 相关文章推荐
javascript 嵌套的函数(作用域链)
Mar 15 Javascript
菜鸟javascript基础资料整理3 正则
Dec 06 Javascript
jQuery 中使用JSON的实现代码
Dec 01 Javascript
jquery日历插件e-calendar升级版
Nov 10 Javascript
Javascript中从学习bind到实现bind的过程
Jan 05 Javascript
vue-cli3全面配置详解
Nov 14 Javascript
JS阻止事件冒泡的方法详解
Aug 26 Javascript
vue.js购物车添加商品组件的方法
Sep 17 Javascript
js中script的上下放置区别,Dom的增删改创建操作实例分析
Dec 16 Javascript
ES6使用 Array.includes 处理多重条件用法实例分析
Mar 02 Javascript
微信小程序开发(二):页面跳转并传参操作示例
Jun 01 Javascript
VUE页面中通过双击实现复制表格中内容的示例代码
Jun 11 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 根据url自动生成缩略图并处理高并发问题
2014/01/23 PHP
mysql_connect localhost和127.0.0.1的区别(网络层阐述)
2015/03/26 PHP
Smarty模板简单配置与使用方法示例
2016/05/23 PHP
php实现的后台表格分页功能示例
2017/10/23 PHP
tp5实现微信小程序多图片上传到服务器功能
2018/07/16 PHP
转一个日期输入控件,支持FF
2007/04/27 Javascript
最近项目写了一些js,水平有待提高
2009/01/31 Javascript
用Greasemonkey 脚本收藏网站会员信息到本地
2009/10/26 Javascript
JavaScript中的onerror事件概述及使用
2013/04/01 Javascript
利用js实现前台动态添加文本框,后台获取文本框内容(示例代码)
2013/11/25 Javascript
js实现Select下拉框具有输入功能的方法
2015/02/06 Javascript
基于Jquery代码实现支持PC端手机端幻灯片代码
2015/11/17 Javascript
js HTML5多图片上传及预览实例解析(不含前端的文件分割)
2016/08/26 Javascript
AngularJS实现星星等级评分功能
2016/09/24 Javascript
利用Js的console对象,在控制台打印调式信息测试Js的实现
2016/11/26 Javascript
用vue快速开发app的脚手架工具
2018/06/11 Javascript
vue实现按需加载组件及异步组件功能
2019/05/27 Javascript
AngularJs的$http发送POST请求,php无法接收Post的数据问题及解决方案
2020/08/13 Javascript
Nodejs 微信小程序消息推送的实现
2021/01/20 NodeJs
python之模拟鼠标键盘动作具体实现
2013/12/30 Python
python实现360的字符显示界面
2014/02/21 Python
Python中tell()方法的使用详解
2015/05/24 Python
python爬取网页内容转换为PDF文件
2020/07/28 Python
Windows下python3.6.4安装教程
2018/07/31 Python
详解pycharm2020.1.1专业版安装指南(推荐)
2020/08/07 Python
python常量折叠基础知识点讲解
2021/02/28 Python
美国领先的奢侈手表在线零售商:WatchMaxx
2017/12/17 全球购物
工商治理实习生的自我评价分享
2014/02/20 职场文书
微信营销策划方案
2014/02/24 职场文书
党员2014两会学习心得体会
2014/03/17 职场文书
在宿舍喝酒的检讨书
2014/09/28 职场文书
2015年社区平安建设工作总结
2015/05/13 职场文书
导师鉴定意见
2015/06/05 职场文书
85句关于理想的名言警句大全
2019/08/22 职场文书
java设计模式--三种工厂模式详解
2021/07/21 Java/Android
python套接字socket通信
2022/04/01 Python