JavaScript 的 OOP 功能解析
根据JavaScript创始人Brandon Eich 自己的说法,JavaScript 最好的语言构造是:
- 函数是一等公民 (first class functions)
- 闭包 (closure)
- Prototypes
- Obj = {p1: 1, P2: ‘abc’}
- Array = [1,2,3]
我认为,JS最精彩的思想是突破了当时OOP的局限性,把object而不是class变成了一等公民(Eich 的1,4,5三条都是这一思想的展现)。
C++,Java,C#等语言其实是class-oriented,强调type,没有作为个体的object的支持,只有“共性”而没有“个性”。JavaScript作为一“动态语言”,理所当然地支持动态地创建object,支持动态地修改object.
下面是我对Eich的补充:
JavaScript object 是一等公民,函数是object的super-set
函数是一个平常的object,它有属性(property),也可以有“member function”,下面的code可以证明这一点:
function foo(x, y)
{
if (foo.xyz === undefined) {
foo.xyz = 0;
}
else {
foo.xyz += x + y;
}
console.log('foo.xyz:' + foo.xyz);
}
foo(1, 2); // 0
foo(1, 2); // 3
foo(1, 2); // 6
上面函数foo定义了property xyz,和一般的object并无异处。
函数也可以有“member function”,下面的code可以证明这一点:
function foo(x, y)
{
var z = (x + y);
console.log('x + y = ' + z);
}
foo.bar = function() { console.log('Hello, I am bar.') };
foo(1, 2); // x + y = 3
foo.bar(); // Hello, I am bar.
但是非函数的object却不能当作函数用, 下面code不会工作:
var obj = {p1: 100};
obj();
结论是:函数是普通的object,并非特殊公民,它无非是 加上个()operator。而 () operator 是个内含“可执行的字符串(executable literal)” 的属性。
JavaScript对class概念的支持
上面说了,JavaScript真正地把object的地位提高到一等,扩展和丰富了我们对OOP的认识。
然而class对于任何一个严肃的OOP工程,仍然是不可缺少,甚至是至关重要的。这就是Eich的第三条:prototype的重要性了。我在咨询过程中,屡屡帮助不喜欢用class的项目合理使用class和class inheritance,大大减少重复代码,提高了程序的抽象性和可维护性。
JavaScript没有class。微软的TypeScript加了class,interface,和inheritance的支持,都是通过函数和prototype实现的。Prototype ,和一等公民的object一起,是实现class的金钥匙。
那么什么是prototype呢,其实它无非是一个函数object的named (命名的)属性罢了。只是这个属性是语言本身附加的,不是编程加上的。它是函数的“共性”,而我们知道class正是object的共性。
我们下面举个例子,看看如何用函数(这里特别称作constructor),和prototype来模拟class
function MyClass(x, y)
{
this.prop1 = x;
this.prop2 = y;
}
MyClass.prototype.getProp1 = function () { console.log('this.prop1:' + this.prop1);}
var obj = {}; // line1: manually create an object
MyClass.call(obj, 10, 20); // line2: call constructor manually on obj1
obj.constructor = MyClass; // line3: set MyClass as obj's constructor manually
callMemberFunc(obj, 'getProp1'); // line4: 10 (simulating member function call)
var obj2 = {}; // line5: manually create another object
MyClass.call(obj2, 30, 40); // line6: call constructor manually on obj2
obj2.constructor = MyClass; // line7: set MyClass as obj's constructor manually
callMemberFunc(obj2, 'getProp1'); // line8: 30 (simulating member function call)
JavaScript的每个函数都有一个prototype属性。其实,这只是方便而已,自己创建一个属性也一样。这个属性的目的是给所有用这个函数的object一个类似于c++ vtble的表格,来添加属性和函数。那么,如何将object和这个prototype挂钩呢?JavaScript给每一位要成为class 中一员的object一个新的属性:constructor。Constructor作为一个ID,来辨识一个特定的class,而这个constructor,当然非负责初始化的函数莫属了!
这一切都可以用JavaScript提供的现有语言构造来手动实现。上面的例子就说明了这一点。
我们的目标是创建MyClass的instances: obj 和 obj2。MyClass 是一个“构造函数”,更确切地说是“初始化函数”。
我们首先手动创建obj (line1),然后call MyClass (line2)来初始化这个新的object, 再把obj 的constructor属性设为MyClass (line3),这样就把obj和MyClass的prototype联系上了。
我们用同样的手段创建了obj2 (line5 ~ line7)。
这两个object 是否属于同一个class呢?是的,有下面两个证明:
A) obj.constructor == obj2.constructor 成立,证明他们同属一个构造函数,即同属一类。
B) callMemberFunc 可以call 任何以MyClass.prototype的函数(line4 和line8)
那么什么是callMemberFunc,它有普遍性吗?答案是肯定的,下面是我的callMemberFunc定义,可以用来call任何函数(需要增强些功能罢了,比如函数参数处理)。
// call a member function for an object
function callMemberFunc(obj, name) {
if (obj[name] !== undefined) {
//console.log('getProp ' + 'found ' + name + ' value:');
return obj[name].call(obj);
}
if (obj.constructor !== undefined) {
//console.log('getProp ' + 'found ' + name + ' in constructor.prototype, value:');
return obj.constructor.prototype[name].call(obj);
}
}
总之,JavaScript通过简单的构造,即可以实现class-oriented程序设计,使得OOP的class功能可以实现。我这里只是部分的实现,但是和JavaScript编译生成的代码,基本功能一致。
JavaScript的syntax sugar,也使得实现上述思想易如反掌:
var obj3 = new MyClass(40, 50); // line9: use 'new' operator
obj3.getProp1(); // line10: 40
JavaScript 的new operator (line9),取代了我上面的手动代码(line1 ~ line3), 而callMemberFunc更是被一个简单的“直接调用”(line10)所取代。
总结
JavaScript程序设计是OOP的全新体验和扩展,将object真正提到了崇高地位,也是在OOP的基础上,将FP (functional programming) 和OOP的一次大统一。
2014-9-1 于西雅图
JavaScript 的 OOP 功能解析的更多相关文章
- JavaScript : DOM文档解析详解
JavaScript DOM 文档解析 1.节点(node):来源于网络理论,代表网络中的一个连接点.网络是由节点构成的集合 <p title=“a gentle reminder”> ...
- JavaScript寻踪OOP之路
上一集中,重点介绍了谁动了你的代码.这里先总结一下:咱们的代码从敲下来到运行出结果,经历了两个阶段:分析期与运行期.在分析期,JavaScript分析器悄悄动了我们的代码:在运行期,JavaScrip ...
- javascript的倒计时功能中newData().getTime()在iOS下会报错问题解决
javascript的倒计时功能中newData().getTime()在iOS下会报错问题解决 在做移动端时间转化为时间戳时,遇到了一个问题,安卓手机上访问时,能拿到时间戳,从而正确转换时间,而在i ...
- HTML5新表单新功能解析
HTML5新增了很多属性功能.但是有兼容性问题,因为这些表单功能新增的.我这里做了一个简单的练习,方便参考.如果完全兼容的话,那我们写表单的时候就省了很多代码以及各种判断. <!DOCTYPE ...
- SQL Server 数据加密功能解析
SQL Server 数据加密功能解析 转载自: 腾云阁 https://www.qcloud.com/community/article/194 数据加密是数据库被破解.物理介质被盗.备份被窃取的最 ...
- 微信小程序0.11.122100版本新功能解析
微信小程序0.11.122100版本新功能解析 新版本就不再吐槽了,整的自己跟个愤青似的.人老了,喷不动了,把机会留给年轻人吧.下午随着新版本开放,微信居然破天荒的开放了开发者论坛.我很是担心官方 ...
- Unity5 新功能解析--物理渲染与standard shader
Unity5 新功能解析--物理渲染与standard shader http://blog.csdn.net/leonwei/article/details/48395061 物理渲染是UNITY5 ...
- JavaScript的OOP编程1
首先要说的是,javascript其实是可以进行OOP编程的,其次javascript的OOP编程实现方式有多种,我写的这一种只是我测试过,可行的一种 version1 // 父类 function ...
- 【原创】Matlab中plot函数全功能解析
[原创]Matlab中plot函数全功能解析 该帖由Matlab技术论(http://www.matlabsky.com)坛原创,更多精彩内容参见http://www.matlabsky.com 功能 ...
随机推荐
- Struts2的注解功能
我们知道通常情况下,Struts2是通过struts.xml配置的.但是随着系统规模的加大我们需要配置的文件会比较大,虽然我们可以根据不同的系统功能将不同模块的配置文件单独书写,然后通过<inc ...
- 【HDOJ】1987 Decoding
简单搜索. /* hdoj 1987 */ #include <iostream> #include <cstdio> #include <cstring> #in ...
- Inotify: 高效、实时的Linux文件系统事件监控框架
Inotify: 高效.实时的Linux文件系统事件监控框架 概要 - 为什么需要监控文件系统? 在日常工作中,人们往往需要知道在某些文件(夹)上都有那些变化,比如: 通知配置文件的改变 ...
- 数据结构(树链剖分,线段树):SDOI 2016 游戏
4515: [Sdoi2016]游戏 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 351 Solved: 157[Submit][Status][ ...
- AC自动机:BZOJ 2434 阿狸的打字机
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1834 Solved: 1053[Submit][Sta ...
- sql server 2008有关SQL的模糊查询
执行 数据库查询时,有完整查询和模糊查询之分. 一般模糊语句如下: SELECT 字段 FROM 表 WHERE 某字段 Like 条件 其中关于条件,SQL提供了四种匹配模式: 1,%:表示任意0个 ...
- ubuntu 下修改host文件
原文地址:http://www.cnblogs.com/kingcat/archive/2012/02/23/2364509.html 有些时候,我们需要让某些域名指向本地,来实现调试,下面介绍下ub ...
- vijos P1243 生产产品(单调队列+DP)
P1243生产产品 描述 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产 品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器 ...
- 《ACM国际大学生程序设计竞赛题解Ⅰ》——模拟题
这篇文章来介绍一些模拟题,即一类按照题目要求将现实的操作转换成程序语言. zoj1003: On every June 1st, the Children's Day, there will be a ...
- MakePic.com 图片制造 打造个性签名 拒绝垃圾邮件 生成个性印章
MakePic.com 图片制造 打造个性签名 拒绝垃圾邮件 生成个性印章 欢迎使用MakePic.com