Javascript属性constructor/prototype的底层原理

在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在原型链中的作用,更实际一点的意义在于:一个子类对象可以获得其父类的所有属性和方法,称之为继承,关于继承我们有好多可以分析和讨论,本篇限于篇幅不在此讨论。

一个容易掉入的陷阱(gotchas) 之前提到constructor易变,那是因为函数的prototype属性容易被更改,我们用时下很流行的编码方式来说明问题,请看下面的示例代码:

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__啦。

因此我们很容易得出结论,这个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的底层原理

时间: 2024-10-25 08:19:13

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

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

1. prototype/__proto__/constructor JS原型链和继承网上已经烂大街了,5毛可以买一堆,这里只提一下: constructor:普通对象和函数对象都有,指向创建它的函数 prototype: 函数对象才有,指向构造函数的原型对象(另一个普通对象) __proto__: 普通对象和函数对象都有,指向创建它的构造函数的原型对象 function Fun1(){}; Fun1.prototype.constructor == Fun1 //true var f2 = n

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

在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. ? 1 2 var arr = []; console.log(Object.prototype.toString.call(arr)) //"[object Array]" 本文要讲的就是,toString方法是如何做到这一点的,原理是什么. ECMAScript 3 在ES3中,Object.prototype.toString方法的规范如下:

深入理解Javascript中this, prototype, constructor

在Javascript面向对象编程中经常需要使用到this,prototype和constructor这3个关键字. 1.首先介绍一下this的使用:this表示当前对象;如果在全局中使用this,则this为当前页面对象window;如果在函数中使用this,则this为调用该函数的对象;可以使用apply和call两个全局函数来改变this的指向. 接下来,首先通过几个demo程序验证一下: function testFunction(){ console.log(this.variable

JavaScript构造函数的prototype属性

JavaScript中没有类的概念,所以其在对象创建方面与面向对象语言有所不同. JS中对象可以定义为"无序属性的集合".其属性可以包含基本值,对象以及函数.对象实质上就是一组没有特定顺序的值,对象中每个属性.方法都有一个名字,每个名字都映射到了一个值,因此我们可以将对象想象称为一个散列表. JS是一种基于对象的语言,对象的概念在JS体系中十分的重要,因此有必要清楚地了解一下JS中对象创建的常用方法及各自的局限性. 使用Object或对象字面量创建对象 工厂模式创建对象 构造函数模式创

javascript对象的属性,方法,prototype作用范围分析

读了篇博客感觉很有用"javascript对象的属性,方法,prototype作用范围分析"就自己写了一遍.以后自己可以用的到. 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://

javascript的constructor属性

/* constructor 属性 constructor 属性返回所有 JavaScript 变量的构造函数. */console.log("John".constructor); // 返回函数 String() { [native code] }console.log((3.14).constructor); // 返回函数 Number() { [native code] }console.log(false.constructor); // 返回函数 Boolean() {

Object.defineProperty() 以及 vue 中双数据绑定的底层原理

Object是在javascript中一个被我们经常使用的类型,而且JS中的所有对象都是继承自Object对象的.虽说我们平时只是简单地使用了Object对象来存储数据,并没有使用到太多其他功能,但是Object对象其实包含了很多很有用的属性和方法,尤其是ES5增加的方法,今天我们先探讨一下Object.defineProperty(). Object.defineProperty 给一个对象添加或者修改属性 返回的是一个对象 语法 Object.defineProperty(obj, prop

对于JavaScript对象的prototype和__proto__的理解

一.Object和Function的关系: 刚学JavaScript的时候,看书上说JavaScript中万物皆对象,而javascript中的其他对象都是从Object继承而来,包括内置对象.瞬间觉得Object碉堡了! 后来,又认识了Function,才知道原来Function才是隐藏在幕后的大BOSS,Object只不过是个大师兄. Object和Function都是JS自带的函数对象,Function比较牛逼点,因为它是Object的构造函数,而且Object的__proto__属性指向

Javascript对象的prototype

转帖: http://www.alloyteam.com/2015/10/prototype/?hmsr=toutiao.io&bsh_bid=928776428 最近恰好有人问起关于 javascript 中的 prototype 相关的问题.特此简单地整理了一下,比较基础,希望能让有类型问题的同学,可以用这篇文章提供参考. prototype 是通过调用构造函数而创建的对象实例的原型对象. 每一个新的函数,都会拥有一个 prototype 属性,这个属性指向函数的原型对象. 所有原型对象都有