Javascript的构造函数和constructor属性


Posted in Javascript onJanuary 09, 2010

例如,在Chrome下调试如下程序,很清楚的展示了这点:

Javascript的构造函数和constructor属性 

然而事情并不是这么简单。再看下面的代码:

Javascript的构造函数和constructor属性
很显然,这个时候obj的constructor已经不再是创建它的函数,注意到obj.name也是undefined,因此修改构造函数的prototype的contructor并不会影响构造函数所产生的对象。真正的原因是:一个对象的constructor是它的构造函数的prototype.constructor,而每一个函数都有一个prototype,默认情况下,这个prototype有一个constructor属性,指向的是它自己。 我觉得Javascript的设计本意是让每个对象的constructor都指向自己的构造函数,然而有像上面的例子可以破坏这一点。另外,这样的设计其实也不很完美,一个很大的问题就是在继承的时候必须小心的维护constructor的指向。在最简单的继承中,可以把子类的构造函数的prototype设置为父类的一个实例,而父类的实例的constructor是父类的构造函数,从而子类的prototype的constructor是父类的构造函数,这就造成了子类的每个对象的构造函数都是父类的构造函数。这是很容易引起困惑的。

最后,再回到上一篇遗留下来的问题,上文谈到Extjs官网给出的一个继承Observable的例子:

Employee = Ext.extend(Ext.util.Observable, { 
constructor: function(config){ 
this.name = config.name; 
this.addEvents({ 
"fired" : true, 
"quit" : true 
}); // Copy configured listeners into *this* object so that the base class's 
// constructor will add them. 
this.listeners = config.listeners; 
// Call our superclass constructor to complete construction process. 
Employee.superclass.constructor.call(config) 
} 
});

这个例子给人的错觉就是你可以重写父类的constructor属性,从而达到改变子类的构造函数的行为的效果。这对于Javascript基础却不深的人是一种误导。 我们再仔细看下Ext.extend的源代码:
extend : function(){ 
// inline overrides 
var io = function(o){ 
for(var m in o){ 
this[m] = o[m]; 
} 
}; 
var oc = Object.prototype.constructor; return function(sb, sp, overrides){ 
if(Ext.isObject(sp)){ 
overrides = sp; 
sp = sb; 
sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; //注意这里 } 
//以下省略………}(), 请注意加注释的那一行。extend如果检测到overrides参数中有constructor属性,也就是说子类试图改写父类的prototype的constructor的时候,就直接将子类设置为这个函数!这样就达到效果了。不过我立刻发现这句检测仅在这个if语句块中,也就是extend的两参数版本中有,那么使用extend的另一个三参数版本这样设置应该是无效的。 写段代码测试下: 
<head> 
<title></title> 
<script type="text/javascript" src="ext-3.1.0/src/core/core/Ext.js"></script> 
<script type="text/javascript"> 
function MyClass() { 
this.id = 'class'; 
} 
function SubClass() { } 
// SubClass=Ext.extend(SubClass, MyClass, { constructor: function() { 
// this.overrideProperty = 'OK'; 
// } 
// }); 
SubClass = Ext.extend(MyClass, { constructor: function() { 
this.overrideProperty = 'OK'; 
} 
}); 
var obj = new SubClass(); 
alert(obj.overrideProperty); 
</script> 
</head>

两种写法,运行的结果果然是第一种是undefined而第二种是OK。呃,名字相同的函数仅仅是参数写法不同,执行的效果却不相同,这个是有点出乎意料的。而且Extjs的官方文档未对此有任何说明。以后大家还是尽量用两参数版本的吧。
最后顺便再看几个表达式,
Javascript的构造函数和constructor属性 
第一个是说函数的prototype的constructor是自己,这个上文已经谈到,没有问题;第二个是说函数也是一个对象,它是Function构造函数的一个对象,也还好理解;第三个是说Function构造函数本身一个对象,它还是Function构造函数的一个对象;最后一个其实是和第三个等价的,是说Function对象的构造函数是它自己…… 我确实有点想不明白Function是怎么自己构造自己的?鸡生蛋,蛋生鸡?要再追究下去就应该涉及到Javascript语言的具体实现了吧,就此打住。

哎,Javascript这个语言本身还是有点复杂啊。要不是有了XMLHttpObject,让它大红大紫了下,否则它还在黑暗的角落里暗自哭泣呢。

作为应用程序开发人员,或许我们自己写程序的并不会用到这些底层的东西,但是,JS框架中却大量的使用了这些高级特性,而且再详尽的文档也不可能把这些方法的作用、影响一一道来,所以开发人员还是需要尽量理解这些东西,以免死了还不知道怎么回事。上面的Ext.extend函数就是一个例子。

Javascript 相关文章推荐
基于javascript的JSON格式页面展示美化方法
Jul 02 Javascript
不使用ajax实现无刷新提交表单
Dec 21 Javascript
JavaScript使表单中的内容显示在屏幕上的方法
Jun 29 Javascript
分享我对JS插件开发的一些感想和心得
Feb 04 Javascript
JavaScript提升性能的常用技巧总结【经典】
Jun 20 Javascript
Javascript中return的使用与闭包详解
Jan 11 Javascript
AngularJS实现的获取焦点及失去焦点时的表单验证功能示例
Oct 25 Javascript
vue计算属性时v-for处理数组时遇到的一个bug问题
Jan 21 Javascript
详解React项目的服务端渲染改造(koa2+webpack3.11)
Mar 19 Javascript
新年快乐! javascript实现超级炫酷的3D烟花特效
Jan 30 Javascript
JQuery实现简单的复选框树形结构图示例【附源码下载】
Jul 16 jQuery
vue封装可复用组件confirm,并绑定在vue原型上的示例
Oct 31 Javascript
jQuery 页面 Mask实现代码
Jan 09 #Javascript
JQuery 遮罩层实现(mask)实现代码
Jan 09 #Javascript
Javascript UrlDecode函数代码
Jan 09 #Javascript
JavaScript 页面坐标相关知识整理
Jan 09 #Javascript
了解jQuery技巧来提高你的代码
Jan 08 #Javascript
在html页面上拖放移动标签
Jan 08 #Javascript
利用js获取服务器时间的两个简单方法
Jan 08 #Javascript
You might like
SMARTY学习手记
2007/01/04 PHP
2014最热门的24个php类库汇总
2014/12/18 PHP
PHP上传图片时判断上传文件是否为可用图片的方法
2016/10/20 PHP
PHP使用微信开发模式实现搜索已发送图文及匹配关键字回复的方法
2017/09/13 PHP
总结PHP代码规范、流程规范、git规范
2018/06/18 PHP
PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
2019/12/12 PHP
JavaScript XML和string相互转化实现代码
2011/07/04 Javascript
jQuery学习笔记之控制页面实现代码
2012/02/27 Javascript
Jquery:ajax实现翻页无刷新功能代码
2013/08/05 Javascript
div模拟滚动条效果示例代码
2013/10/16 Javascript
js实现简单的左右两边固定广告效果实例
2015/04/10 Javascript
C++中的string类的用法小结
2015/08/07 Javascript
jQuery实现自动与手动切换的滚动新闻特效代码分享
2015/08/27 Javascript
js省市联动效果完整实例代码
2015/12/09 Javascript
IONIC自定义subheader的最佳解决方案
2016/09/22 Javascript
使用jQuery实现简单的tab框实例
2017/08/22 jQuery
详解最新vue-cli 2.9.1的webpack存在问题
2017/12/16 Javascript
VUE 直接通过JS 修改html对象的值导致没有更新到数据中解决方法分析
2019/12/02 Javascript
element-ui table行点击获取行索引(index)并利用索引更换行顺序
2020/02/27 Javascript
通过JS判断网页是否为手机打开
2020/10/28 Javascript
基于ajax实现上传图片代码示例解析
2020/12/03 Javascript
Python中join和split用法实例
2015/04/14 Python
详解python使用递归、尾递归、循环三种方式实现斐波那契数列
2018/01/16 Python
详解用Python实现自动化监控远程服务器
2019/05/18 Python
python增加图像对比度的方法
2019/07/12 Python
Python实现猜年龄游戏代码实例
2020/03/25 Python
python爬虫利器之requests库的用法(超全面的爬取网页案例)
2020/12/17 Python
Numpy中的数组搜索中np.where方法详细介绍
2021/01/08 Python
美国家居装饰和豪华家具购物网站:One Kings Lane
2018/12/24 全球购物
离婚协议书怎么写(范本参考)
2014/09/30 职场文书
营销计划书范文
2015/01/17 职场文书
出租车拒载检讨书
2015/01/28 职场文书
工作调动申请报告
2015/05/18 职场文书
会议主持词通用版
2019/04/02 职场文书
Go使用协程交替打印字符
2021/04/29 Golang
MySQL EXPLAIN输出列的详细解释
2021/05/12 MySQL