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 相关文章推荐
jQuery使用数组编写图片无缝向左滚动
Dec 11 Javascript
JS中处理时间之setUTCMinutes()方法的使用
Jun 12 Javascript
javascript实现的网站访问量统计代码
Dec 20 Javascript
Node.js+Express配置入门教程
May 19 Javascript
jQuery+PHP实现微信转盘抽奖功能的方法
May 25 Javascript
详解webpack + react + react-router 如何实现懒加载
Nov 20 Javascript
js 取消页面可以选中文字的功能方法
Jan 02 Javascript
jQuery幻灯片插件owlcarousel参数说明中文文档
Feb 27 jQuery
Angular中使用better-scroll插件的方法
Mar 27 Javascript
Vue中使用ElementUI使用第三方图标库iconfont的示例
Oct 11 Javascript
基于Vue实现可以拖拽的树形表格实例详解
Oct 18 Javascript
node.js爬虫框架node-crawler初体验
Oct 29 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
解析VS2010利用VS.PHP插件调试PHP的方法
2013/07/19 PHP
javascript与CSS复习(二)
2010/06/29 Javascript
Jquery公告滚动+AJAX后台得到数据
2011/04/14 Javascript
在chrome浏览器中,防止input[text]和textarea在聚焦时出现黄色边框的解决方法
2011/05/24 Javascript
用jquery中插件dialog实现弹框效果实例代码
2013/11/15 Javascript
JavaScript字符串对象fromCharCode方法入门实例(用于把Unicode值转换为字符串)
2014/10/17 Javascript
全面了解JavaScript对象进阶
2016/07/19 Javascript
AngularJS 与Bootstrap实现表格分页实例代码
2016/10/14 Javascript
JavaScript、C# URL编码、解码总结
2017/01/21 Javascript
详解Vue.js 2.0 如何使用axios
2017/04/21 Javascript
backbone简介_动力节点Java学院整理
2017/07/14 Javascript
vue-cli2.x项目优化之引入本地静态库文件的方法
2018/06/19 Javascript
jQuery实现获取选中复选框的值实例详解
2018/06/28 jQuery
vue.js使用watch监听路由变化的方法
2018/07/08 Javascript
区别JavaScript函数声明与变量声明
2018/09/12 Javascript
Node.js操作系统OS模块用法分析
2019/01/04 Javascript
浅谈react-router@4.0 使用方法和源码分析
2019/06/04 Javascript
解决vue-cli@3.xx安装不成功的问题及搭建ts-vue项目
2020/02/09 Javascript
js实现从右往左匀速显示图片(无缝轮播)
2020/06/29 Javascript
封装 axios+promise通用请求函数操作
2020/08/11 Javascript
[01:53]3.19 DOTA2发布会 现场精彩Coser表演
2014/03/25 DOTA
Python类定义和类继承详解
2015/05/08 Python
利用Python2下载单张图片与爬取网页图片实例代码
2017/12/25 Python
对python:print打印时加u的含义详解
2018/12/15 Python
python中threading开启关闭线程操作
2020/05/02 Python
python能否java成为主流语言吗
2020/06/22 Python
tensorflow与numpy的版本兼容性问题的解决
2021/01/08 Python
医疗保健专业人士购物网站:Scrubs & Beyond
2017/02/08 全球购物
北美最大的手工艺品零售商之一:Michaels Stores
2019/02/27 全球购物
J2EE的优越性主要表现在哪些方面
2016/03/28 面试题
文职个人求职信范文
2013/09/23 职场文书
医院党员公开承诺书
2014/08/30 职场文书
优秀共产党员演讲稿
2014/09/04 职场文书
党的群众路线个人对照检查材料
2014/09/23 职场文书
烟台的海导游词
2015/02/02 职场文书
求职自荐信该如何书写?
2019/06/24 职场文书