js 原型对象和原型链理解


Posted in Javascript onFebruary 09, 2017

一个例子让你彻底明白原型对象和原型链

开篇

之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述。有一句话说的好:如果你不能把一个很复杂的东西用最简单的话语描述出来,那就说明你没有真正的理解。最近正在读《Javascript高级程序设计》,书中对原型对象和原型链的描述让我受益匪浅,下面仅用一个对比性的例子来说明。

我们经常会这么写

function Person () {
 this.name = 'John';
 }
 var person = new Person();
 Person.prototype.say = function() {
 console.log('Hello,' + this.name);
 };
 person.say();//Hello,John

上述代码非常简单,Person原型对象定义了公共的say方法,虽然此举在构造实例之后出现,但因为原型方法在调用之前已经声明,因此之后的每个实例将都拥有该方法。从这个简单的例子里,我们可以得出:

原型对象的用途是为每个实例对象存储共享的方法和属性,它仅仅是一个普通对象而已。并且所有的实例是共享同一个原型对象,因此有别于实例方法或属性,原型对象仅有一份。所有就会有如下等式成立:

person.say == new Person().say

可能我们也会这么写

function Person () {
 this.name = 'John';
 }
 var person = new Person();
 Person.prototype = {
 say: function() {
  console.log('Hello,' + this.name);
 }
 };
 person.say();//person.say is not a function

很不幸,person.say方法没有找到,所以报错了。其实这样写的初衷是好的:因为如果想在原型对象上添加更多的属性和方法,我们不得不每次都要写一行Person.prototype,还不如提炼成一个Object来的直接。但是此例子巧就巧在构造实例对象操作是在添加原型方法之前,这样就会造成一个问题:

当var person = new Person()时,Person.prototype为:Person {}(当然了,内部还有constructor属性),即Person.prototype指向一个空的对象{}。而对于实例person而言,其内部有一个原型链指针proto,该指针指向了Person.prototype指向的对象,即{}。接下来重置了Person的原型对象,使其指向了另外一个对象,即

Object {say: function},

这时person.proto的指向还是没有变,它指向的{}对象里面是没有say方法的,因为报错。

从这个现象我们可以得出:

在js中,对象在调用一个方法时会首先在自身里寻找是否有该方法,若没有,则去原型链上去寻找,依次层层递进,这里的原型链就是实例对象的__proto__属性。

若想让上述例子成功运行,最简单有效的方法就是交换构造对象和重置原型对象的顺序,即:

function Person () {
 this.name = 'John';
 }
 Person.prototype = {
 say: function() {
  console.log('Hello,' + this.name);
 }
 };
 var person = new Person();
 person.say();//person.say is not a function

一张图让你秒懂原型链

js 原型对象和原型链理解

其实,只需要明白原型对象的结构即可:

Function.prototype = {
 constructor : Function,
 __proto__ : parent prototype,
 some prototype properties: ...
 };

总结:函数的原型对象constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针__proto__,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用__proto__一直指向Object的原型对象上,而Object的原型对象用Object.__proto__ = null表示原型链的最顶端,如此变形成了javascript的原型链继承,同时也解释了为什么所有的javascript对象都具有Object的基本方法。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
深入理解JavaScript系列(1) 编写高质量JavaScript代码的基本要点
Jan 15 Javascript
关于全局变量和局部变量的那些事
Jan 11 Javascript
读取input:file的路径并显示本地图片的方法
Sep 23 Javascript
JQuery操作元素的css样式
Mar 09 Javascript
浅谈类似于(function(){}).call()的js语句
Mar 30 Javascript
js实现横向拖拽导航条功能
Feb 17 Javascript
用React实现一个完整的TodoList的示例代码
Oct 30 Javascript
解决Linux无法正常安装与卸载Node.js的方法
Jan 19 Javascript
vue单页缓存方案分析及实现
Sep 25 Javascript
vue cli3.0 引入eslint 结合vscode使用
May 27 Javascript
VUE 自定义组件模板的方法详解
Aug 30 Javascript
vue-以文件流-blob-的形式-下载-导出文件操作
Aug 07 Javascript
AngularJs表单校验功能实例代码
Feb 09 #Javascript
javascript 显示全局变量与隐式全局变量的区别
Feb 09 #Javascript
JS获取本周周一,周末及获取任意时间的周一周末功能示例
Feb 09 #Javascript
简单谈谈Javascript函数中的arguments
Feb 09 #Javascript
javascript 中设置window.location.href跳转无效问题解决办法
Feb 09 #Javascript
微信小程序之picker日期和时间选择器
Feb 09 #Javascript
BootStrap 弹出层代码
Feb 09 #Javascript
You might like
图解上海144收音机
2021/03/02 无线电
咖啡店都有些什么常规豆子呢?有什么风味在里面
2021/03/04 咖啡文化
一个高ai的分页函数和一个url函数
2006/10/09 PHP
php的curl封装类用法实例
2014/11/07 PHP
php rsa加密解密使用详解
2015/01/14 PHP
PHP之预定义接口详解
2015/07/29 PHP
PHP实现的简单操作SQLite数据库类与用法示例
2017/06/19 PHP
利用laravel+ajax实现文件上传功能方法示例
2017/08/13 PHP
jquery插件推荐 jquery.cookie
2014/11/09 Javascript
JS+CSS实现可拖拽的漂亮圆角特效弹出层完整实例
2015/02/13 Javascript
基于jQuery实现复选框是否选中进行答题提示
2015/12/10 Javascript
AngularJS入门教程之ng-checked 指令详解
2016/08/01 Javascript
JS如何设置iOS中微信浏览器的title
2016/11/22 Javascript
深入理解jquery的$.extend()、$.fn和$.fn.extend()
2017/07/08 jQuery
基于vue-simplemde实现图片拖拽、粘贴功能
2018/04/12 Javascript
JavaScript DOM元素常见操作详解【添加、删除、修改等】
2018/05/09 Javascript
jQuery实现的简单拖拽功能示例【测试可用】
2018/08/14 jQuery
Node+OCR实现图像文字识别功能
2018/11/26 Javascript
koa+mongoose实现简单增删改查接口的示例代码
2019/05/13 Javascript
JS端基于download.js实现图片、视频时直接下载而不是打开预览
2020/05/09 Javascript
实例讲解React 组件
2020/07/07 Javascript
vue离开当前页面触发的函数代码
2020/09/01 Javascript
Python Property属性的2种用法
2015/06/21 Python
python调用c++传递数组的实例
2019/02/13 Python
解决安装python3.7.4报错Can''t connect to HTTPS URL because the SSL module is not available
2019/07/31 Python
pandas中遍历dataframe的每一个元素的实现
2019/10/23 Python
python中实现栈的三种方法
2020/12/19 Python
AmazeUi Tree(树形结构) 应用小结
2020/08/17 HTML / CSS
佛罗里达州印第安河新鲜水果:Hale Groves
2017/02/20 全球购物
PHP数据运算类型都有哪些
2013/11/05 面试题
幼儿园教师辞职信
2014/01/18 职场文书
鲜果饮品店创业计划书
2014/01/21 职场文书
工资收入证明样本(5篇)
2014/09/16 职场文书
市委召开党的群众路线教育实践活动总结大会报告
2014/10/21 职场文书
餐饮服务食品安全承诺书
2015/04/29 职场文书
动画《朋友游戏》公开佐藤友生绘制的开播纪念绘
2022/04/06 日漫