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);//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】

 
 
 实例对象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;实例对象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的控制台效果

  如果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);//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的三角关系

    × 目录 [1]图示 [2]概念 [3]说明[4]总结 前面的话 javascript里的关系又多又乱.作用域链是一种单向的链式关系,还算简单清晰:this机制的调用关系,稍微有些复杂:而关于原型,则 ...

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

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

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

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

  4. 怎样理解prototype对象的constructor属性

    function Person(name){ this.name = name; } var lilei = new Person("Lilei"); lilei.construc ...

  5. prototype、proto、constructor 之间的关系

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

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

  7. javascript中prototype、constructor以及__proto__之间的三角关系

    三者暧昧关系简单整理 在javascript中,prototype.constructor以及__proto__之间有着“著名”的剪不断理还乱的三角关系,楼主就着自己对它们的浅显认识,来粗略地理理以备 ...

  8. Javascript Prototype __proto__ constructor 三者的关系

    JavaScript三大毒瘤 --- this,原型链,作用域 在我等菜鸟一步一步升级中的过程中,这三个概念总是困扰这我们(可能只有我吧,我比较蠢).这三个东西往往都很绕,今天我就来分享一下我对原型. ...

  9. 深入理解JavaScript原型:prototype,__proto__和constructor

    JavaScript语言的原型是前端开发者必须掌握的要点之一,但在使用原型时往往只关注了语法,其深层的原理并未理解透彻.本文结合笔者开发工作中遇到的问题详细讲解JavaScript原型的几个关键概念, ...

随机推荐

  1. ajax+FormData+javascript 实现无刷新上传附件

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  2. 武汉科技大学ACM :1008: A+B for Input-Output Practice (VIII)

    Problem Description Your task is to calculate the sum of some integers. Input Input contains an inte ...

  3. bootstrap兼容IE8的一些注意

    准备 bootstrap 3.3.5 jQuery 1.12.0 注意 支持html5 需要引入html5.js 支持placeholder 需要引入placeholder.js ie8 不支持 fo ...

  4. 跟我学android-搭建Android开发环境(一)

    Android官网地址:http://developer.android.com/,下载和安装 AndroidSDK请按如下步骤进行: 下载ADT 和SDK:http://developer.andr ...

  5. PHP中检测ajax请求的代码例子

    多数情况下,基于JavaScript 的Js框架如jquery.Mootools.Prototype等,在发出Ajax请求指令时,都会发送额外的 HTTP_X_REQUESTED_WITH 头部信息, ...

  6. C++实现Log()日志函数

    转载请注明原创:http://www.cnblogs.com/StartoverX/p/4600649.html 需求:Log()函数,能够自动根据时间记录日志信息,要求不定参数类型和参数个数. 第一 ...

  7. 对PHP安全有帮助的一些函数

    安全一直是一个在编程语言中非常值得去关注的方面.在任何一种成熟的编程语言中都有合适的办法来保证程序的安全性,在现代的 WEB 开发中 安全一直是一个在编程语言中非常值得去关注的方面.在任何一种成熟的编 ...

  8. NET MVC+EF6+Bootstrap

    开源:ASP.NET MVC+EF6+Bootstrap开发框架   前言 我在博客园潜水两三年了,在这里看过很多大神的文章,也学到了很多东西.可以说我是汲取着博客园的营养成长的. 想当年,我也是拿1 ...

  9. 公司内部SQUID代理HTTPS访问资料网站

    同事安装SQUID,我按如下方法加密: 参考URL: http://www.tuicool.com/articles/iYv2YfU 众所周知,在国内访问国外互联网经常无法访问,比如要找资料googl ...

  10. Iterator pattern(c++实现)

    概述: 在现在的电视机中,我们使用[后一个]和[前一个]按钮可以很方便的换台,当按下[后一个]按钮时,将切换到下一个预置的频道.想象一下在陌生的城市中的旅店中看电视.当改变频道时,重要的不是几频道,而 ...