图解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 相关文章推荐
使用jquery读取html5 localstorage的值的方法
Jan 04 Javascript
js调用后台、后台调用前台等方法总结
Apr 17 Javascript
javascript闭包(Closure)用法实例简析
Nov 30 Javascript
JS中的hasOwnProperty()和isPrototypeOf()属性实例详解
Aug 11 Javascript
JS去除字符串中空格的方法
Feb 14 Javascript
微信小程序实现顶部选项卡(swiper)
Jun 19 Javascript
vue与vue-i18n结合实现后台数据的多语言切换方法
Mar 08 Javascript
详解在React-Native中持久化redux数据
May 22 Javascript
Vue.js实现备忘录功能
Jun 26 Javascript
浅谈layui 绑定form submit提交表单的注意事项
Oct 25 Javascript
javascript实现页面的实时时钟显示示例
Aug 06 Javascript
jQuery-App输入框实现实时搜索
Nov 19 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编程语言开发动态WAP页面
2006/10/09 PHP
我的论坛源代码(二)
2006/10/09 PHP
php 异常处理实现代码
2009/03/10 PHP
PHP多进程编程实例
2014/10/15 PHP
PHP实现图片上传并压缩
2015/12/22 PHP
php生成短网址/短链接原理和用法实例分析
2020/05/29 PHP
javascript之学会吝啬 精简代码
2010/04/25 Javascript
不用构造函数(Constructor)new关键字也能实现JavaScript的面向对象
2013/01/11 Javascript
JavaScript类属性的访问方式详解
2014/02/11 Javascript
Javascript获取CSS伪元素属性的实现代码
2014/09/28 Javascript
原生js实现日期联动
2015/01/12 Javascript
基于JS实现PHP的sprintf函数实例
2015/11/14 Javascript
理解JavaScript中Promise的使用
2016/01/18 Javascript
详解Javascript数据类型的转换规则
2016/12/12 Javascript
js数字滑动时钟的简单实现(示例讲解)
2017/08/14 Javascript
vue slot 在子组件中显示父组件传递的模板
2018/03/02 Javascript
详解关于element el-button使用$attrs的一个注意要点
2018/11/09 Javascript
让你30分钟快速掌握vue3教程
2020/10/26 Javascript
利用python3随机生成中文字符的实现方法
2017/11/24 Python
详解使用Python下载文件的几种方法
2019/10/13 Python
keras 特征图可视化实例(中间层)
2020/01/24 Python
详细分析Python垃圾回收机制
2020/07/01 Python
css3.0新属性效果在ie下的解决方案
2010/05/10 HTML / CSS
用CSS3实现无限循环的无缝滚动的实例代码
2017/07/04 HTML / CSS
电脑教师的自我评价
2013/12/18 职场文书
校本教研工作方案
2014/01/14 职场文书
《石榴》教学反思
2014/03/02 职场文书
商场客服专员岗位职责
2014/06/13 职场文书
正风肃纪剖析材料
2014/09/30 职场文书
公司承诺函范文
2015/01/21 职场文书
2015年个人审计工作总结
2015/04/07 职场文书
青涩记忆观后感
2015/06/18 职场文书
2016年综治和平安建设宣传月活动总结
2016/04/01 职场文书
详解CSS开发过程中的20个快速提升技巧
2021/05/21 HTML / CSS
Vue实现动态查询规则生成组件
2021/05/27 Vue.js
Pytorch中使用ImageFolder读取数据集时忽略特定文件
2022/03/23 Python