前面的话

  javascript里的关系又多又乱。作用域链是一种单向的链式关系,还算简单清晰;this机制的调用关系,稍微有些复杂;而关于原型,则是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);//
console.log(f1.a);//
console.log(f2.a);//

【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】

  实例对象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的控制台效果
 
【第二部分: Object】
  Foo.prototype是f1的原型对象,同时它也是实例对象。实际上,任何对象都可以看做是通过Object()构造函数的new操作实例化的对象
  所以,Foo.prototype作为实例对象,它的构造函数是Object(),原型对象是Object.prototype。相应地,构造函数Object()的prototype属性指向原型对象Object.prototype;实例对象Foo.prototype的proto属性同样指向原型对象Object.prototype
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的控制台效果

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

【第三部分: Function】

 
 

  前面已经介绍过,函数也是对象,只不过是具有特殊功能的对象而已。任何函数都可以看做是通过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.prototype);//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

一张图理解prototype、proto和constructor的三角关系的更多相关文章

  1. [转] 一张图理解prototype、proto和constructor的三角关系

    前面的话 javascript里的关系又多又乱.作用域链是一种单向的链式关系,还算简单清晰:this机制的调用关系,稍微有些复杂:而关于原型,则是prototype.proto和constructor ...

  2. JS 一张图理解prototype、proto和constructor的关系

    转载于原文地址:https://www.cnblogs.com/xiaohuochai/p/5721552.html(感谢大神的总结) 前面的话 javascript里的关系又多又乱.作用域链是一种单 ...

  3. 理解prototype、proto和constructor的三角关系

    javascript里的关系又多又乱.作用域链是一种单向的链式关系,还算简单清晰:this机制的调用关系,稍微有些复杂:而关于原型,则是prototype.proto和constructor的三角关系 ...

  4. prototype、proto和constructor的三角关系

    转载整理自http://www.cnblogs.com/xiaohuochai/p/5721552.html#3760057 http://blog.csdn.net/jasonzds/article ...

  5. 一张图理解RACSignal的Subscription过程

    通过下面一张图理解RACSignal的调用过程: 创建signale RACSignal通过子类[RACDynamicSignal createSignal:]方法获得Signal,并将disSubs ...

  6. 几张图理解Roll, Pitch, Yaw的含义

    Roll:翻滚    Pitch:俯仰    Yaw:偏航 有时候不知道它到底绕着哪个轴旋转得到的角,一个比较容易的记法是根据字母的排列顺序PRY分别对应XYZ轴进行旋转得到的角,即: Pitch是绕 ...

  7. 深入理解javascript作用域系列第五篇——一张图理解执行环境和作用域

    × 目录 [1]图示 [2]概念 [3]说明[4]总结 前面的话 对于执行环境(execution context)和作用域(scope)并不容易区分,甚至很多人认为它们就是一回事,只是高程和犀牛书关 ...

  8. 8张图理解Java

    一图胜千言,下面图解均来自Program Creek 网站的Java教程,目前它们拥有最多的票选.如果图解没有阐明问题,那么你可以借助它的标题来一窥究竟. 1.字符串不变性 下面这张图展示了这段代码做 ...

  9. 【转】8张图理解Java

    一图胜千言,下面图解均来自Program Creek 网站的Java教程,目前它们拥有最多的票选.如果图解没有阐明问题,那么你可以借助它的标题来一窥究竟. 1.字符串不变性 下面这张图展示了这段代码做 ...

随机推荐

  1. mysql问题总结

    1. You are using safe update mode and you tried to update a table without a WHERE clause that uses a ...

  2. Angular初步

    一.angular.js是什么? angular.js是一个javascript的框架,与jquery是一个级别的,区别是jquery主要是擅长dom操作,而angular主要是擅长绑定数据显示数据. ...

  3. 安装zabbix-3.0.3+nginx-1.10.1+php-5.6.22

    好久没有接触监控类的软件了,今天抽空搭建了下最新的版本 首先系统环境 zabbix-server-1 192.168.11.11   centos6.7 mysql-server    192.168 ...

  4. 二、JSP、servlet、SQL三者之间的数据传递(前台与后台数据交互)

    2.收信息来到表单提交时URL所指向的servlet文件,获取传递过来的参数值

  5. MVC项目中ExecutionTimeout不生效的解决方案

    我们做web服务器端开发时,经常会遇到一个需求场景,因为某些耗时处理造成页面的响应处理时间超长,技术角度就想能否给页面处理程序一个指定的超时时间,服务端处理程序执行时间超过这个指定的超时时间则中断处理 ...

  6. css中单位px、pt、em和rem的区别

    国内的设计师大都喜欢用px,而国外的网站大都喜欢用em和rem,那么三者有什么区别,又各自有什么优劣呢? px :像素(Pixel).相对长度单位.像素px是相对于显示器屏幕分辨率而言的.(引自CSS ...

  7. JavaScript 作用域知识点梳理

    JavaScript的作用域一直以来是前端开发中难以理解的知识点,对于JavaScript的作用域主要记住几句话. 一.“JavaScript” 中无块级作用域 在   Java 或 C# 中存在块级 ...

  8. java的jxl技术导入Excel

    项目结构: http://www.cnblogs.com/hongten/gallery/image/112177.html 在项目中我们看到Reference Libraries中的jxl.jar包 ...

  9. SQL Server 汉字转拼音

    IF OBJECT_ID('Fn_GetQuanPin','Fn') IS NOT NULL DROP FUNCTION fn_GetQuanPin go )) ) as begin ),) decl ...

  10. 安卓 自定义AlertDialog对话框(加载提示框)

    AlertDialog有以下六种使用方法: 一.简单的AlertDialog(只显示一段简单的信息) 二.带按钮的AlertDialog(显示提示信息,让用户操作) 三.类似ListView的Aler ...