在Javascript语言中,constructor属性是专门为function而设计的,它存在于每个function的prototype属性中。

这个constructor保存了指向function的一个引用。

在定义一个函数(代码例如以下所看到的)时,



function F() {

    // some code

 }



JavaScript内部会运行例如以下几个动作:

为该函数加入一个原形属性(即prototype对象).

为prototype对象额外加入一个constructor属性。而且该属性保存指向函数F的一个引用。



这样当我们把函数F作为自己定义构造函数来创建对象的时候。对象实例内部会自己主动保存一个指向其构造函数(这里就是我们的自己定义构造函数F)的prototype对象的一个属性__proto__。所以我们在每个对象实例中就能够訪问构造函数的prototype所有拥有的所有属性和方法。就好像它们是实例自己的一样。

当然该实例也有一个constructor属性了(从prototype那里获得的),这时候constructor的作用就非常明显了,由于在这时,每个对象实例都能够通过constrcutor对象訪问它的构造函数,请看以下代码:

 







[javascript] view plaincopy









var f = new F();

alert(f.constructor === F);// output true

alert(f.constructor === F.prototype.constructor);// output true





我们能够利用这个特性来完毕以下的事情: 对象类型推断,如







[javascript] view plaincopy









if(f.constructor === F) {

    // do sth with F

}





事实上constructor的出现原本就是用来进行对象类型推断的,可是constructor属性易变。不可信赖。

我们有一种更加安全可靠的判定方法:instanceof 操作符。

以下代码仍然返回true



if(f instanceof F) {

    // do sth with F

}.



原型链继承。因为constructor存在于prototype对象上,因此我们能够结合constructor沿着原型链找到最原始的构造函数,如以下代码:



function Base() {

}

// Sub1 inherited from Base through prototype chain

function Sub1() {

}

Sub1.prototype = new Base();

Sub1.prototype.constructor = Sub1;

Sub1.superclass = Base.prototype;

// Sub2 inherited from Sub1 through prototype chain

function Sub2() {

}

Sub2.prototype = new Sub1();

Sub2.prototype.constructor = Sub2;

Sub2.superclass = Sub1.prototype;

// Test prototype chain

alert(Sub2.prototype.constructor);

// function Sub2(){}

alert(Sub2.superclass.constructor);

// function Sub1(){}

alert(Sub2.superclass.constructor.superclass.constructor);

// function Base(){}



上面的样例仅仅是为了说明constructor在原型链中的作用,更实际一点的意义在于:一个子类对象能够获得其父类的全部属性和方法。称之为继承,关于继承我们有好多能够分析和讨论,本篇限于篇幅不在此讨论。

一个easy掉入的陷阱(gotchas) 之前提到constructor易变,那是由于函数的prototype属性easy被更改。我们用时下非常流行的编码方式来说明问题。请看以下的演示样例代码:



function F() {



}

F.prototype = {

    _name:Eric,

    getName: function () {

        return this._name;

    }

}



初看这样的方式并无问题。可是你会发现以下的代码失效了:

var f = new F();

alert(f.constructor === F); // output false

怎么回事?F不是实例对象f的构造函数了吗?

当然是!

仅仅只是构造函数F的原型被开发人员重写了。这样的方式将原有的prototype对象用一个对象的字面量{}来取代。

而新建的对象{}仅仅是Object的一个实例,系统(或者说浏览器)在解析的时候并不会在{}上自己主动加入一个constructor属性,由于这是function创建时的专属操作。仅当你声明函数的时候解析器才会做此动作。

然而你会发现constructor并非不存在的,以下代码能够測试它的存在性:

alert(typeof f.constructor == ‘undefined’);// output false

既然存在。那这个constructor是从哪儿冒出来的呢?

我们要回头分析这个对象字面量{}。

由于{}是创建对象的一种简写,所以{}相当于是new Object()。

那既然{}是Object的实例,自然而然他获得一个指向构造函数Object()的prototype属性的一个引用__proto__,又由于Object.prototype上有一个指向Object本身的constructor属性。

所以能够看出这个constructor事实上就是Object.prototype的constructor,以下代码能够验证其结论:

alert(f.constructor === Object.prototype.constructor);//output true

alert(f.constructor === Object);// also output true

一个解决的方法就是手动恢复他的constructor。以下代码很好地攻克了这个问题:



function F() {

}

F.prototype = {

    constructor: F, /* reset constructor */

    _name: Eric,

    getName: function () {

        return this._name;

    }

};



之后一切恢复正常。constructor又一次获得的构造函数的引用,我们能够再一次測试上面的代码。这次返回true

var f = new F();

alert(f.constructor === F); // output true this time ^^

解惑:构造函数上怎么另一个constructor?它又是哪儿来的?

细心的朋友会发现,像JavaScript内建的构造函数,如Array, RegExp, String, Number, Object, Function等等竟然自己也有一个constructor:

alert(typeof Array.constructor != ‘undefined’);// output true

经过測试发现。此物非彼物它和prototype上constructor不是同一个对象,他们是共存的:

alert(typeof Array.constructor != ‘undefined’);// output true

alert(typeof Array.prototype.constructor === Array); // output true

只是这件事情也是好理解的,由于构造函数也是函数。

是函数说明它就是Function构造函数的实例对象。自然他内部也有一个指向Function.prototype的内部引用__proto__啦。

因此我们非常easy得出结论,这个constructor(构造函数上的constructor不是prototype上的)事实上就是Function构造函数的引用:

alert(Array.constructor === Function);// output true

alert(Function.constructor === Function); // output true

OK, constructor从此真相大白,你不在对它陌生了

本文转自:原帖地址:http://blog.csdn.net/hikvision_java_gyh/article/details/8937157

Javascript属性constructor/prototype的底层原理的更多相关文章

  1. JavaScript 原型和对象创建底层原理

    1. prototype/__proto__/constructor JS原型链和继承网上已经烂大街了,5毛可以买一堆,这里只提一下: constructor:普通对象和函数对象都有,指向创建它的函数 ...

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

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

  3. [javascript基础]constructor与prototype

    最初对js中 object.constructor 的认识: 在学习JS的面向对象过程中,一直对constructor与prototype感到很迷惑,看了一些博客与书籍,觉得自己弄明白了,现在记录如下 ...

  4. 深入理解Javascript中this, prototype, constructor

    在Javascript面向对象编程中经常需要使用到this,prototype和constructor这3个关键字. 1.首先介绍一下this的使用:this表示当前对象;如果在全局中使用this,则 ...

  5. JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能

    摘要: 理解浏览器渲染. 原文:JavaScript是如何工作的: CSS 和 JS 动画底层原理及如何优化它们的性能 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 这是专门探索 J ...

  6. JavaScript中的 prototype 和 constructor

    prototype属性  任何js函数都可以用作构造函数, 而构造函数需要用到prototype属性, 因此, 每个js函数F(除了ES5的Function.bind()方法返回的函数外) 都自动拥有 ...

  7. JavaScript中Object.prototype.toString方法的原理

    在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. ? 1 2 var arr = []; console.lo ...

  8. Javascript object.constructor属性与面向对象编程(oop)

    定义和用法 在 JavaScript 中, constructor 属性返回对象的构造函数. 返回值是函数的引用,不是函数名: JavaScript 数组 constructor 属性返回 funct ...

  9. javascript中的prototype和constructor

    构造函数 我们知道,ECMAScript5中的Object.Array.Date.RegExp.Function等引用类型都是基于构造函数的,他们本身就是ECMAScript5原生的构造函数.比如,我 ...

随机推荐

  1. 使用dom4j工具包对xml文件解析

    xml文件 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http: ...

  2. Visual Studio跨平台开发(4):Xamarin Android控制项介绍

    前言 不同于iOS, Xamarin 在Visual Studio中针对Android, 可以直接设计使用者界面. 在本篇教学文章中, 笔者会针对Android的专案目录结构以及基本控制项进行介绍, ...

  3. MVC5下的switchbutton

    最近想提高代码生成的时候,是否选择显示样式好看些,所以想到了SwitchButton. 但是碰到个问题是,添加页面的这个初始值,需要写成true或者false 包括修改页面做个判断的话,渲染的做法也是 ...

  4. Python与数据结构[1] -> 栈/Stack[0] -> 链表栈与数组栈的 Python 实现

    栈 / Stack 目录 链表栈 数组栈 栈是一种基本的线性数据结构(先入后出FILO),在 C 语言中有链表和数组两种实现方式,下面用 Python 对这两种栈进行实现. 1 链表栈 链表栈是以单链 ...

  5. bzoj2440(莫比乌斯函数)

    bzoj2440 题意 求第 k 个不是完全平方数(除 1 以外)的正倍数的数. 分析 利用二分法求解,二分 x ,判断 x 是否是第 k 个数即可,那么我们就要计算 [1, x] 有几个符合条件的数 ...

  6. 洛谷——P1614 爱与愁的心痛

    题目背景 (本道题目隐藏了两首歌名,找找看哪~~~) <爱与愁的故事第一弹·heartache>第一章 <我为歌狂>当中伍思凯神曲<舞月光>居然没赢给萨顶顶,爱与愁 ...

  7. C++中数据对齐问题。struct、union、enum,类继承。再谈sizeof()

    首先是struct,在C++中,结构体其实和class有很大的相似了.但是有一点不同的是,struct默认是public,而class中是private. 当然,struct继承等用法也是可以的. 共 ...

  8. 图论常用算法之一 POJ图论题集【转载】

    POJ图论分类[转] 一个很不错的图论分类,非常感谢原版的作者!!!在这里分享给大家,爱好图论的ACMer不寂寞了... (很抱歉没有找到此题集整理的原创作者,感谢知情的朋友给个原创链接) POJ:h ...

  9. 关于MapControl和PageLayout地图同步的问题

    按照ArcMap的处理方式,地图和制图是分两个页面的,他们之间通过共享同一个Map对象来实现地图同步,具体做法就是在PageLayoutControl的PageLayoutReplaced事件发生时, ...

  10. Delphi制作QQ自动登录器源码

    Delphi制作QQ自动登录器源码  http://www.cnblogs.com/sunsoft/archive/2011/02/25/1964967.html 以TM2009为例,检查了一下,未登 ...