简洁优雅的JavaScript OOP风格
还是以老生常谈的User举例子,说明已在代码注释中。
function User() { /** * constant */ var MAX_AGE = 100; var MIN_AGE = 10; /** * private variable */ var m_iAge = -1; /** * constructor */ function Init() { alert("User object init!"); } /** * private method */ function checkAge(age) { return MIN_AGE<=age && age<=MAX_AGE; } /** * public method */ function setAge(age) { if(checkAge(age)) { m_iAge = age; } } function dispAge() { alert(m_iAge); } /** * Export */ this.setAge = setAge; this.dispAge = dispAge; Init(); } var oUser = new User(); oUser.setAge(11); oUser.dispAge();
之所以推荐这种风格,不仅仅看起来像传统的OOP代码结构,更重要的是抛弃了this这个东西后,代码的清晰以及运行效率的提高。
显然在此模型中,是不会用到一个this来读取或设置变量的。因为无论成员变量还是函数,都是以类的闭包形式定义的,有别于以往用map[key]的方式,因此访问他们只需名字即可,而无需this,在类的内部来看每个方法都是当做private的。至于要在类的外部访问,在结尾处做一个导出指明即可。有点类似windows下导入DLL中函数,在def文件里说明下。
最后就是构造函数。之所以单独放在一个Init函数里,不单是风格上的独立性,关键是让他在类的初始化过程中最后执行,保证所有的成员级变量都已定义(成员变量可以定义在Init函数的后面)。
至于运行效率。虽然每次初始化对象的时候需要多执行接口导出函数的代码,但该模型从头到尾都没有提到prototype这个概念,所以运行时期间,访问任何一个方法都无需查找原型链表,而是最直接的键值访问。在实际应用中,对象的使用当然比创建要频繁的多。
这种设计模式更适合使用在单例模型(Singleton)当中:
var objDemo = new function() { // // 同上 // };
从而避免了类似这样的代码:
var objDemo = { _x:0, _y:0, test: function(){alert(this._x + this._y); } };
细心的朋友可能发现了这个模型的缺点,就是没有了public的属性,而必须用getter和setter。确实如此,虽然大多数时候都是用getter和setter来设置访问属性,但是直接的变量访问更为灵活,有时也更有效率。所以这个模型在灵活性上多了份限制。
作者: EtherDream 发表于 2011-03-07 13:25 原文链接