图解prototype、proto和constructor的三角关系


Posted in Javascript onJuly 31, 2016

javascript里的关系又多又乱。作用域链是一种单向的链式关系,还算简单清晰;this机制的调用关系,稍微有些复杂;而关于原型,则是prototype、proto和constructor的三角关系。本文先用一张图开宗明义,然后详细解释原型的三角关系

图示图解prototype、proto和constructor的三角关系

概念

上图中的复杂关系,实际上来源就两行代码

function Foo(){};var f1 = new Foo;

【构造函数】

用来初始化新创建的对象的函数是构造函数。在例子中,Foo()函数是构造函数

【实例对象】

通过构造函数的new操作创建的对象是实例对象。可以用一个构造函数,构造多个实例对象

function Foo(){};
var f1 = new Foo;
var f2 = new Foo;
console.log(f1 === f2);//false

【原型对象及prototype】

构造函数有一个prototype属性,指向实例对象的原型对象。通过同一个构造函数实例化的多个对象具有相同的原型对象。经常使用原型对象来实现继承

function Foo(){};
Foo.prototype.a = 1;
var f1 = new Foo;
var f2 = new Foo;console.log(Foo.prototype.a);
//1
console.log(f1.a);//1
console.log(f2.a);//1

【constructor】

原型对象有一个constructor属性,指向该原型对象对应的构造函数

function Foo(){};
console.log(Foo.prototype.constructor === Foo);//true

由于实例对象可以继承原型对象的属性,所以实例对象也拥有constructor属性,同样指向原型对象对应的构造函数

function Foo(){};
var f1 = new Foo;
console.log(f1.constructor === Foo);//true

【proto】

实例对象有一个proto属性,指向该实例对象对应的原型对象

function Foo(){};
var f1 = new Foo;
console.log(f1.__proto__ === Foo.prototype);//true

说明

概念介绍完了,现在对图示的关系进行详细说明

function Foo(){};
var f1 = new Foo;

【第一部分: Foo】

图解prototype、proto和constructor的三角关系

实例对象f1是通过构造函数Foo()的new操作创建的。构造函数Foo()的原型对象是Foo.prototype;实例对象f1通过__proto__属性也指向原型对象Foo.prototype

function Foo(){};
var f1 = new Foo;
console.log(f1.__proto === Foo.prototype);//true

实例对象f1本身并没有constructor属性,但它可以继承原型对象Foo.prototype的constructor属性

function Foo(){};
var f1 = new Foo;console.log(Foo.prototype.constructor === Foo);//true
console.log(f1.constructor === Foo);//true
console.log(f1.hasOwnProperty('constructor'));//false

下图是实例对象f1的控制台效果

图解prototype、proto和constructor的三角关系

【第二部分: Object】

图解prototype、proto和constructor的三角关系

Foo.prototype是f1的原型对象,同时它也是实例对象。实际上,任何对象都可以看做是通过Object()构造函数的new操作实例化的对象

所以,Foo.prototype作为实例对象,它的构造函数是Object(),原型对象是Object.prototype。相应地,构造函数Object()的prototype属性指向原型对象Object;实例对象Foo.prototype的proto属性同样指向原型对象Object

function Foo(){};
var f1 = new Foo;
console.log(Foo.prototype.__proto__ === Object.prototype);//true

实例对象Foo.prototype本身具有constructor属性,所以它会覆盖继承自原型对象Object.prototype的constructor属性

function Foo(){};
var f1 = new Foo;
console.log(Foo.prototype.constructor === Foo);//true
console.log(Object.prototype.constructor === Object);//true
console.log(Foo.prototype.hasOwnProperty('constructor'));//true

下图是实例对象Foo.prototype的控制台效果

图解prototype、proto和constructor的三角关系

如果Object.prototype作为实例对象的话,其原型对象是什么,结果是null。私以为,这可能也是typeof null的结果是'object'的原因之一吧

console.log(Object.prototype.__proto__ === null);//true

【第三部分: Function】

图解prototype、proto和constructor的三角关系

前面已经介绍过,函数也是对象,只不过是具有特殊功能的对象而已。任何函数都可以看做是通过Function()构造函数的new操作实例化的结果

如果把函数Foo当成实例对象的话,其构造函数是Function(),其原型对象是Function.prototype;类似地,函数Object的构造函数也是Function(),其原型对象是Function.prototype

function Foo(){};
var f1 = new Foo;console.log(Foo.__proto__ === Function.prototype);//true
console.log(Object.__proto__ === Function.prototype);//true

原型对象Function.prototype的constructor属性指向构造函数Function();实例对象Object和Foo本身没有constructor属性,需要继承原型对象Function.prototype的constructor属性

function Foo(){};
var f1 = new Foo;
console.log(Function.prototype.constructor === Function);//true
console.log(Foo.constructor === Function);//true
console.log(Foo.hasOwnProperty('constructor'));//false
console.log(Object.constructor === Function);//true
console.log(Object.hasOwnProperty('constructor'));//false

所有的函数都可以看成是构造函数Function()的new操作的实例化对象。那么,Function可以看成是调用其自身的new操作的实例化的结果

所以,如果Function作为实例对象,其构造函数是Function,其原型对象是Function.prototype

console.log(Function.__proto__ === Function.prototype);//true
console.log(Function.prototype.constructor === Function);//true
console.log(Function.prototype === Function);//true

如果Function.prototype作为实例对象的话,其原型对象是什么呢?和前面一样,所有的对象都可以看成是Object()构造函数的new操作的实例化结果。所以,Function.prototype的原型对象是Object.prototype,其原型函数是Object()

console.log(Function.prototype.__proto__ === Object.prototype);//true

第二部分介绍过,Object.prototype的原型对象是null

console.log(Object.prototype.__proto__ === null);//true

总结

【1】函数(Function也是函数)是new Function的结果,所以函数可以作为实例对象,其构造函数是Function(),原型对象是Function.prototype

【2】对象(函数也是对象)是new Object的结果,所以对象可以作为实例对象,其构造函数是Object(),原型对象是Object.prototype

【3】Object.prototype的原型对象是null

Javascript 相关文章推荐
动态加载js文件 document.createElement
Oct 14 Javascript
Microsfot .NET Framework4.0框架 安装失败的解决方法
Aug 14 Javascript
js特殊字符转义介绍
Nov 05 Javascript
js this函数调用无需再次抓获id,name或标签名
Mar 03 Javascript
在easyUI开发中,出现jquery.easyui.min.js函数库问题的解决办法
Sep 11 Javascript
JavaScript页面实时显示当前时间实例代码
Oct 23 Javascript
jQuery 插件封装的方法
Nov 16 Javascript
原生JS简单实现ajax的方法示例
Nov 29 Javascript
JavaScript 中Date对象的格式化代码方法汇总
Sep 06 Javascript
微信小程序之滚动视图容器的实现方法
Sep 26 Javascript
vue实现微信获取用户信息的方法
Mar 21 Javascript
html中两种获取标签内的值的方法
Jun 16 jQuery
JavaScript数据类型转换的注意事项
Jul 31 #Javascript
关于JavaScript 原型链的一点个人理解
Jul 31 #Javascript
jquery实现界面无刷新加载登陆注册
Jul 30 #Javascript
AngularJS ng-change 指令的详解及简单实例
Jul 30 #Javascript
Javascript中级语法快速入手
Jul 30 #Javascript
AngularJS ng-blur 指令详解及简单实例
Jul 30 #Javascript
AngularJS ng-bind-template 指令详解
Jul 30 #Javascript
You might like
PHP日期时间函数的高级应用技巧
2009/05/16 PHP
PHP检查网站是否宕机的方法示例
2017/07/24 PHP
jqPlot jquery的页面图表绘制工具
2009/07/25 Javascript
jquery tab标签页的制作
2010/05/10 Javascript
JavaScript的document对象和window对象详解
2010/12/30 Javascript
修改好的jquery滚动字幕效果实现代码
2011/06/22 Javascript
电子商务网站上的常用的js放大镜效果
2011/12/08 Javascript
JavaScript基础知识之数据类型
2012/08/06 Javascript
jQuery中end()方法用法实例
2015/01/08 Javascript
JavaScript禁止微信浏览器下拉回弹效果
2017/05/16 Javascript
详解Vue 非父子组件通信方法(非Vuex)
2017/05/24 Javascript
Vue.js移动端左滑删除组件的实现代码
2017/09/08 Javascript
mpvue微信小程序多列选择器用法之省份城市选择的实现
2019/03/07 Javascript
Vue项目中Api的组织和返回数据处理的操作
2019/11/04 Javascript
详解vue-router的Import异步加载模块问题的解决方案
2020/05/13 Javascript
node.js文件的复制、创建文件夹等相关操作
2021/02/05 Javascript
利用 Chrome Dev Tools 进行页面性能分析的步骤说明(前端性能优化)
2021/02/24 Javascript
[01:38:19]夜魇凡尔赛茶话会 第五期
2021/03/11 DOTA
python遍历文件夹并删除特定格式文件的示例
2014/03/05 Python
Django框架中处理URLconf中特定的URL的方法
2015/07/20 Python
Python程序员面试题 你必须提前准备!(答案及解析)
2018/01/23 Python
Python 批量合并多个txt文件的实例讲解
2018/05/08 Python
Python SQL查询并生成json文件操作示例
2018/08/17 Python
django实现web接口 python3模拟Post请求方式
2019/11/19 Python
35款精致的 CSS3 和 HTML5 网页模板 推荐
2012/08/03 HTML / CSS
CSS3 制作绽放的莲花采用效果叠加实现
2013/01/31 HTML / CSS
我的网上商城创业计划书
2013/12/26 职场文书
工资收入证明
2014/10/07 职场文书
社区党建工作汇报材料
2014/10/27 职场文书
2014年纳税评估工作总结
2014/12/23 职场文书
小学英语教学随笔
2015/08/14 职场文书
python 机器学习的标准化、归一化、正则化、离散化和白化
2021/04/16 Python
SpringBoot集成Redis,并自定义对象序列化操作
2021/06/22 Java/Android
「我的青春恋爱物语果然有问题。-妄言录-」第20卷封面公开
2022/03/21 日漫
简单聊聊Golang中defer预计算参数
2022/03/25 Golang
微软Win11 全新照片应用面向 Dev预览版推出 新版本上手体验图集
2022/09/23 数码科技