JavaScript constructor和instanceof,JSOO中的一对欢喜冤家


Posted in Javascript onMay 25, 2009

至少每个尝试JavaScriptOO的程序员都花费很多精力用在面向对象机制的模拟上而非业务本身.
这对Java,C++甚至Php的开发者来讲都是难以想象的.
更糟糕的是模拟OO对于JavaScript高级程序员都有着邪恶的吸引.
因为干这个事儿超然于业务之上,有种创造新编程语言一般的快感,可以令IQ尽情挥洒.
正如前些年大家都想把自个网站的common.js写成个框架一样.直到YUI,JQuery等等的强势推出才稍有平息.
然而虽然各个框架都有对JavaScriptOO模拟,但还未到有谁谁谁可以一桶糨糊的时候吧.
或许江湖就不需要的霸主出现,抑或大家只要等到JS2.0+就好了.
如果说可以new就是面向对象,那显然JavaScript在这方面是非常不错的.

function Person(name){ 
this.name = name; 
} 
var lenel = new person("lenel"); 
alert(lenel.constructor === Person); 
alert(lenel instanceof Person === true); 
alert(lenel instanceof Object === true);

到此为止,一切都很和谐.
对象的constructor正如字面上的意义指向构造它的Person.
对象是构造它的Person的一个实例(instance).
所有对象都是Object的实例,像极了Java.
JavaScript提供原型(prototype)的方式来实现方法拓展和继承
Person.prototype.getName = function(){ 
return this.name 
};

这样定义了之后所有对象都具有了getName的方法.
当然也可以将写在对象构造时
function Person(name){ 
this.name = name; 
this.getName = function(){ 
return this.name; 
}; 
}

但是这种做法不仅是带来额外性能损耗这点瑕疵,也不仅是带来了可以访问私有变量的特权.
它与使用prototype的写法还会其他有不同之处,不过这不是本文的重点.
接下来,我们想到继承,很常见的写法是这样的.
function Stuff(name,id){ 
this.name = name; 
this.id = id; 
} 
Stuff.prototype = new Person(); 
var piupiu = new Stuff("piupiu","007"); 
alert(piupiu.getName());

非常好,继承了getName方法;
考察下instanceof
alert(piupiu instanceof Stuff === true); 
alert(piupiu instanceof Person === true);

非常好,说明了Stuff和Person是有关系的.piupiu是它俩的实例,非常Java.
接下来再考察下constructor
alert(piupiu.constructor === Stuff);//false 
test(piupiu.constructor === Person);//true

问题出现了明明new的Stuff为啥constructor却是Person,
在这儿将道理也是强词夺理,我们只好记住结论
结论:对象的constructor属性并非指向其构造器,而是指向其构造器的prototype属性的constructor属性
文字功底太差,自己读过都觉得没说清楚
放在这里:
对象piupiu的constructor属性指向的是其构造器Stuff的prototype属性的constructor属性
因为Stuff.prototype = new Person();
所以Stuff.prototype.constructor === Person.
所以piupiu.consturctor === Person.
以上的结论不仅仅在对象继承的时候才出现,在定义对象时
function Student(name){ 
this.name = name; 
} 
Student.prototype = { 
getName:function(){ 
return this.name; 
}, 
setName:function(name){ 
this.name = name; 
} 
}

如果方法比较多,常常会这样写,看起来规矩一些.
其实这种写法同样牺牲了constructor
var moen = new Student("moen"); 
alert(moen.constructor === Student);//false 
alert(moen.constructor === Object);//true

因为在{}相当于new Object(),所以根据上面的结论prototype={}时,constructor变了.
保卫constructor!继承时我们用一个循环来把父类的方法copyto子类
function Stuff1(name,id){ 
this.name = name; 
this.id = id; 
} 
for(var fn in Person.prototype){ 
Stuff1.prototype[fn] = Person.prototype[fn]; 
} 
var piupiu1 = new Stuff1("piupiu1","008"); 
alert(piupiu1.getName() === "piupiu1"); 
alert(piupiu1.constructor === Stuff1);

It works!当我们兴冲冲的把父类的方法都继承下来的时候,我们却丢失了父子关系.
alert(piupiu1 instanceof Stuff1 === true);//true 
alert(piupiu1 instanceof Person === true);//false

显然,我们没有说过Stuff1是继承至Person啊,只一个for循环能说明什么呢.
这好像是一对矛盾..顾此必失彼.
所以叻,深入使用对象的时候,甚至你一不小心,都会让instantceof和constructor丢去字面的含义.
所以叻,在使用框架的时候,如果提供了继承功能,如果不试不会知道你为了继承放弃了哪个.
所以叻,模拟OO时就必须要提供替代这两个字面含义的属性或方法的实现,而且必须让使用者知道!
模拟OO绝对不只这个问题,在子类方法中调用父类的同名方法,这个OO语言常见的特性,
JavaScript实现起来也非常困难,大师们基本都有各自的一套,只不过有些用心去做了用起来相比之下更自然些,如Base库.
当然可以摒弃instanceof和constructor的使用,就当不知道有这么一回儿事儿,活儿仍可继续,死不了人的.
但如果你不是单枪匹马作战,那就通知你的Partner也摒弃这对冤家吧.
类似今天这点事儿,老鸟们都清楚的很,但如果不是团队中每个人都有统一的认识,那就是隐患.
一个好玩儿的现象<<JavaScript高级程序设计>>强调instanceof,而<<精通JavaScript>>强调constructor.而各自对另一个一笔带过或只字不提.怨念..甚深...
Javascript 相关文章推荐
javascript基础的动画教程,直观易懂
Jan 10 Javascript
Javascript学习笔记9 prototype封装继承
Jan 11 Javascript
json-lib出现There is a cycle in the hierarchy解决办法
Feb 24 Javascript
利用javascript的面向对象的特性实现限制试用期
Aug 04 Javascript
JS 实现点击a标签的时候让其背景更换
Oct 15 Javascript
关于编写性能高效的javascript事件的技术
Nov 28 Javascript
javascript实现在网页中运行本地程序的方法
Feb 03 Javascript
AngularJS $injector 依赖注入详解
Sep 14 Javascript
微信小程序 扎金花简单实例
Feb 21 Javascript
javascript实现自由编辑图片代码详解
Jun 21 Javascript
在vue中使用axios实现post方式获取二进制流下载文件(实例代码)
Dec 16 Javascript
Node.js 中判断一个文件是否存在
Aug 24 Javascript
jQuery 图像裁剪插件Jcrop的简单使用
May 22 #Javascript
document.compatMode介绍
May 21 #Javascript
各种常用浏览器getBoundingClientRect的解析
May 21 #Javascript
简单的js分页脚本
May 21 #Javascript
input+select(multiple) 实现下拉框输入值
May 21 #Javascript
一些Javascript的IE和Firefox(火狐)兼容性的问题总结及常用例子
May 21 #Javascript
Javascript 兼容firefox的一些问题
May 21 #Javascript
You might like
php学习笔记 面向对象的构造与析构方法
2011/06/13 PHP
php微信公众号开发之答题连闯三关
2018/10/20 PHP
用Laravel轻松处理千万级数据的方法实现
2020/12/25 PHP
firefox插件Firebug的使用教程
2010/01/02 Javascript
元素的内联事件处理函数的特殊作用域在各浏览器中存在差异
2011/01/12 Javascript
js 判断脚本加载完毕的代码
2011/07/13 Javascript
js判断子窗体是否关闭的方法
2015/08/11 Javascript
javascript中arguments,callee,caller详解
2016/03/16 Javascript
angular4自定义组件详解
2017/09/28 Javascript
利用JS hash制作单页Web应用的方法详解
2017/10/10 Javascript
vue.js中toast用法及使用toast弹框的实例代码
2018/08/27 Javascript
原生js实现公告滚动效果
2021/01/10 Javascript
vue中的inject学习教程
2019/04/24 Javascript
CKeditor4 字体颜色功能配置方法教程
2019/06/26 Javascript
js实现石头剪刀布游戏
2020/10/11 Javascript
[51:28]EG vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/16 DOTA
Python数据结构之顺序表的实现代码示例
2017/11/15 Python
python merge、concat合并数据集的实例讲解
2018/04/12 Python
python使用RNN实现文本分类
2018/05/24 Python
python实现超市扫码仪计费
2018/05/30 Python
Python3实现爬取简书首页文章标题和文章链接的方法【测试可用】
2018/12/11 Python
基于python框架Scrapy爬取自己的博客内容过程详解
2019/08/05 Python
在IE6系列等老式浏览器中使用HTML5的新标签实现方案
2012/12/25 HTML / CSS
Probikekit日本:自行车套件,跑步和铁人三项装备
2017/04/03 全球购物
GafasWorld哥伦比亚:网上购买眼镜
2017/11/28 全球购物
WoolOvers澳洲官方网站:英国针织服装公司
2018/05/13 全球购物
意大利咖啡、浓缩咖啡和浓缩咖啡机:illy caffe
2019/03/20 全球购物
Tea Collection官网:一家位于旧金山的童装公司
2020/08/07 全球购物
关于母亲节的感言
2014/02/04 职场文书
2014年工程工作总结
2014/11/25 职场文书
网络新闻该怎么写?这些写作技巧你都知道吗?
2019/08/26 职场文书
《中华上下五千年》读后感3篇
2019/11/29 职场文书
只需要这一行代码就能让python计算速度提高十倍
2021/05/24 Python
Python人工智能之混合高斯模型运动目标检测详解分析
2021/11/07 Python
一文弄懂MySQL中redo log与binlog的区别
2022/02/15 MySQL
Python四款GUI图形界面库介绍
2022/06/05 Python