JS原型链 详解及示例代码


Posted in Javascript onSeptember 06, 2016

前言

在 segmentfault 上看到这样一道题目:

var F = function(){};
Object.prototype.a = function(){};
Function.prototype.b = function(){};
var f = new F();

问:f 能取到a,b吗?原理是什么?

乍一看真的有点懵,仔细研究了一下,发现还是对原型理解不透彻,所以总结一篇,填个洞~

Function和Object

在解题之前,先再说说 原型、原型链,以及 Function 和 Object 的关系,这也是本文的重点。

原型

在创建一个函数的时候,会自动为其创建一个原型对象,可以通过函数的prototype属性访问到。

创建一个构造函数的实例对象,该实例对象内部将包含一个指针(内部属性),指向构造函数的原型对象。ECMA-262 第5版中管这个指针叫[[prototype]]。虽然在脚本中没有标准的方式访问[[prototype]],但Firefox、 Safari、 Chrome在每个对象上都支持一个属性 __proto__,用于访问其构造函数的原型对象。

重要的事情再说一遍:
构造函数通过 prototype 属性访问原型对象。
实例对象通过 [[prototype]] 内部属性访问原型对象,浏览器实现了 _proto_ 属性用于实例对象访问原型对象。

var F = function () {};
var f = new F();
// 假设F的原型对象是 p, 则
// F.prototype === p;
// f.__proto__ === p;

再重复一遍。。prototype说的是构造函数和原型对象之间的关系,__proto__说的是实例对象和原型对象之间的关系。

原型链

类 A继承B,B继承C……其实就是A的原型对象中有指针指向B的原型对象,而B的原型对象中有指针指向C的原型对象……注意是原型对象之间的联系,A B C 这三个构造函数之间并没什么关系,所以才称为“原型链”吧~

假设a是A的实例对象,则 a 的原型链为下图中紫色线条所示,橙色线条连接了构造函数和其原型对象。

JS原型链 详解及示例代码

由图可以看出,原型链的末端是Object.prototype.__proto__即null。当查找a的某个属性或方法时,首先查找a自身有没有,没有则沿着原型链一直查找,直到找到或者最后到null返回undefined。

Function 和 Object

Function 和 Object 之间的关系有点绕:

Object 是构造函数,既然是函数,那么就是Function的实例对象;Function是构造函数,但Function.prototype是对象,既然是对象,那么就是Object的实例对象。

一切对象都是Object的实例,一切函数都是Function的实例。

Object是Function的实例,而Function.prototype是Object的实例。

二者的关系如下图所示。

JS原型链 详解及示例代码

可见,Object作为构造函数,它有 prototype 属性指向 Object.prototype , 作为实例对象, 它有 Object.__proto__ 指向Function.prototype。Function是构造函数,它有prototype属性指向Function.prototype,而Function是函数,从而也是Function的实例,所以它有Function.__proto__指向Function.prototype,从而 Function.__proto__ === Function.prototype 为 true。

可在Chrome控制台下进行验证,如图。

JS原型链 详解及示例代码

原题解析

解决原型链问题最好的办法就是画图了,经过前面的分析,这个图画起来应该不成问题,如下~

JS原型链 详解及示例代码

f 的原型链为蓝色线所画,所以 f 可以访问到 a , 不能访问到 b 。

如果不画图,乍一看,可能会觉得f 可以访问到 b,那是可能跟我一样误认为F.prototype指向Function.prototype,但其实F.prototype是对象而不是函数,所以它的原型对象不会是 Function.prototype。

所以,原型链问题一应要画图啊~

原题扩展

在上题中,f 只能访问 a,不能访问 b 。但 F 既可以访问 a ,又可以访问 b。如果把题修改成下面的样子, F.b()的结果是什么呢?为什么呢?可以想一下哦~

var F = function(){};
Object.prototype.a = function(){};
Function.prototype.b = function(){ console.log('F.__proto__') };
F.prototype.b = function (){console.log('F.prototype');};

总结

读到这里,有没有发现函数一个比较特殊的地方?

一般的对象,只有一个__proto__属性用于访问其构造函数的原型对象,而对于函数来说,它既是函数又是对象。

作为函数,它生来就有prototype属性指向其原型对象函数名.prototype。

作为Function的实例对象,它有__proto__属性指向Function.prototype

通常,这两个属性是指向两个对象的,但Function的这两个属性指向相同,都指向Function.prototype。

对于函数 A( ) 来说,A.prototype 中的方法是供其实例对象调用的,自己并不会用;当A 作为实例运行时,调用的是A.__proto__ 中的方法。也就是说,作为构造函数使用时,走的是A.prototype这条链,方法、属性赋给其实例;作为对象使用时,走的是A.__proto__这条链。在不同的场景下,分清它的身份就不会错了。

整篇下来,感觉自己说的也比较絮叨……不足之处,还请各位指正~ 至于题目,真的不知道该叫什么好。。

愿本文能带给坚持看完的你一些收获~ ^_^

谢谢大家对本站的支持,后续继续更新相关资料,帮助大家学习了解这部分知识!

Javascript 相关文章推荐
基于jquery的direction图片渐变动画效果
May 24 Javascript
jquery如何获取复选框的值
Dec 12 Javascript
一个简单的jquery进度条示例
Apr 28 Javascript
JavaScript实现标题栏文字轮播效果代码
Oct 24 Javascript
基于jQuery实现鼠标点击导航菜单水波动画效果附源码下载
Jan 06 Javascript
自己动手制作基于jQuery的Web页面加载进度条插件
Jun 03 Javascript
图解prototype、proto和constructor的三角关系
Jul 31 Javascript
详解React之父子组件传递和其它一些要点
Jun 25 Javascript
React SSR样式及SEO的实践
Oct 22 Javascript
Bootstarp在pycharm中的安装及简单的使用方法
Apr 19 Javascript
在JavaScript中使用严格模式(Strict Mode)
Jun 13 Javascript
Vue-CLI项目中路由传参的方式详解
Sep 01 Javascript
JavaScript中push(),join() 函数 实例详解
Sep 06 #Javascript
jquery实现全选、不选、反选的两种方法
Sep 06 #Javascript
fullpage.js全屏滚动插件使用实例
Sep 06 #Javascript
AngularJS  $on、$emit和$broadcast的使用
Sep 05 #Javascript
JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)
Sep 05 #Javascript
Vuejs第六篇之Vuejs与form元素实例解析
Sep 05 #Javascript
Vue表单实例代码
Sep 05 #Javascript
You might like
PHP开发框架kohana中处理ajax请求的例子
2014/07/14 PHP
WordPress中查询文章的循环Loop结构及用法分析
2015/12/17 PHP
php简单解析mysqli查询结果的方法(2种方法)
2016/06/29 PHP
php json中文编码为null的解决办法
2016/12/14 PHP
许愿墙中用到的函数
2006/10/07 Javascript
javascript面向对象之Javascript 继承
2010/05/04 Javascript
Javascript(AJAX)解析XML的代码(兼容FIREFOX/IE)
2010/07/11 Javascript
javascript中的prototype属性实例分析说明
2010/08/09 Javascript
iframe子页面与父页面在同域或不同域下的js通信
2014/05/07 Javascript
js中键盘事件实例简析
2015/01/10 Javascript
QQ登录背景闪动效果附效果演示源码下载
2015/09/22 Javascript
Vue.js第三天学习笔记(计算属性computed)
2016/12/01 Javascript
bootstrap daterangepicker汉化以及扩展功能
2017/06/15 Javascript
在vue中created、mounted等方法使用小结
2020/07/21 Javascript
[47:35]VP vs Pain 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/20 DOTA
动感网页相册 python编写简单文件夹内图片浏览工具
2016/08/17 Python
python 3.6 +pyMysql 操作mysql数据库(实例讲解)
2017/12/20 Python
TensorFlow实现iris数据集线性回归
2018/09/07 Python
django富文本编辑器的实现示例
2019/04/10 Python
python隐藏终端执行cmd命令的方法
2019/06/24 Python
python 实现多维数组转向量
2019/11/30 Python
Pycharm内置终端及远程SSH工具的使用教程图文详解
2020/03/19 Python
Marriott国际:万豪国际酒店查询预订
2017/09/25 全球购物
英国川宁茶官方网站:Twinings茶
2019/05/21 全球购物
Farfetch巴西官网:奢侈品牌时尚购物平台
2020/10/19 全球购物
委托与事件是什么关系?为什么要使用委托
2014/04/18 面试题
幼儿园义卖活动方案
2014/01/17 职场文书
扩大国家免疫规划实施方案
2014/03/21 职场文书
禁烟标语大全
2014/06/11 职场文书
师范大学生求职信
2014/06/13 职场文书
本科应届生求职信
2014/08/05 职场文书
遗嘱格式范本
2015/08/07 职场文书
2019商业计划书格式、范文
2019/04/24 职场文书
导游词之澳门妈祖庙
2019/12/19 职场文书
学会用Python实现滑雪小游戏,再也不用去北海道啦
2021/05/20 Python
SpringBoot使用ip2region获取地理位置信息的方法
2022/06/21 Java/Android