`
ruilin215
  • 浏览: 1148340 次
  • 性别: Icon_minigender_2
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

再议《JavaScript代码优化一例》

阅读更多

今天收到《程序员》第8期,读到杨建华先生的“JavaSctipt代码优化一例”。仔细读来,觉得所做优化未能尽彻。所以专写一篇文章来讨论杨先生的例子。原例可以在杨先生的blog上找到:
http://prowyh.spaces.live.com/blog/cns!EAAA8AB356F88EA0!403.entry

一、正则表达式的创建代码
---
这样的创建代码实在冗余:
var fnRE = /functor_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}/i;
var objRE = /object_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}$/i;
var objRE_r = /radio_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_r/i;
var objRE_a = /object_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_a/i;
var objRE_m = /radio_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_m/i;
var objRE_d = /radio_[0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12}_d/i;

仔细读来,其实就是一个添加前后缀的GUID。那么可否写成如下:
var GUID = '([0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12})';
var fnRE = new RegExp('(functor_)'+ GUID, 'i');
var objRE = new RegExp('(object_)' + GUID + '$', 'i');
var objRE_r = new RegExp('(radio_)' + GUID + '_(r)', 'i');
var objRE_a = new RegExp('(object_)' + GUID + '_(a)', 'i');
var objRE_m = new RegExp('(radio_)' + GUID + '_(m)', 'i');
var objRE_d = new RegExp('(radio_)' + GUID + '_(d)', 'i');

这里看起来是用了字符串连接运算,但由于变量声明只运算一次,因此对效率没什么影响。而且可读性强了,修改起来也方便。
读注意这里用到了正则表达式中的分组'( )',这在后面是会很有用的。

二、正则使用中的分组
---
代码总是通过
aryAList[_match[0].split("_")[1]] = "a_";
这样的形式来从匹配中分离GUID,但如果使用上面的分组,那么这项运算就不必要了。简单的使用
aryAList[_match[2]] = "a_";
就可以得到结果。

三、应注意DOM引用的耗时
---
代码中,在循环内不断地访问DOM对象的成员,然而DOM对象的成员存取是耗时的。更细的说,每一个成员
都会通过COM组件封装,因此效率是差的。所以下面的代码:
else if ((_match = _obj.name.match(objRE_m)) != null) {
}
else if ((_match = _obj.name.match(objRE_d)) != null) {
}
应当被改作:
var name = _obj.name;
else if ((_match = name.match(objRE_m)) != null) {
}
else if ((_match = name.match(objRE_d)) != null) {
}

四、过于复杂的逻辑
---
代码过于依赖其它语言的编程经验,而忽略了JavaScript的自身特性。因此实现的逻辑中规中矩,但是难以
扩展,而且复杂。例如循环中的大量if..else if ...连用。后文单独给出这部分的优化。

五、从StringBuilder()接口来看,优化程度不够
---
文章提到StringBuilder是一个字符串构建的高效对象。我留意到它的使用是:
objectListEx.append(_id + ":" + _r + ":" + _a + ":" + _m + ":" + _d + ";");
那么可以说这个对象的优化是不够的。因为这里传入一个字符串参数,而传入参数又用字符串连接运算,
效率提升很有限。
如果StringBuilder是用array.join来实现字符串拼接的话,那么更加良好的方式是允许在append中使用多
个参数。例如:
objectListEx.append = function() {
this.push.apply(this, arguments);
}
objectListEx.toString = function() {
return this.join('');
}
那么,上例的添加就可以写成:
objectListEx.append(_id , ":" , _r , ":" , _a , ":" , _m , ":" , _d , ";");
这就避免了多余的字符串连接运算。

六、新的优化后版本
---
// optimized version
var functorListEx = new StringBuilder();
var objectListEx = new StringBuilder();

var coll = document.getElementsByTagName("INPUT");

// regular expression for matching
var GUID = '([0-9A-Za-z]{8}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{4}-[0-9A-Za-z]{12})';
var fnRE = new RegExp('(functor_)'+ GUID, 'i');
var objRE = new RegExp('(object_)' + GUID + '$', 'i');
var objRE_r = new RegExp('(radio_)' + GUID + '_(r)', 'i');
var objRE_a = new RegExp('(object_)' + GUID + '_(a)', 'i');
var objRE_m = new RegExp('(radio_)' + GUID + '_(m)', 'i');
var objRE_d = new RegExp('(radio_)' + GUID + '_(d)', 'i');

// helper data structures used by optimized algorithm
var aryObjList = new Array();
var aryRList = new Array();
var aryAList = new Array();
var aryMList = new Array();
var aryDList = new Array();

var aryList = {
r: aryRList,
a: aryAList,
m: aryMList,
d: aryDList
}

// one pass scan to traverse the nodes collection (coll) to build functorListEx
// and intermediate arrays
for (var i=0,imax=coll.length; i<imax; i++) {
var _obj = coll[i];
if (!_obj.checked) continue; // <-- 更快的检测
if (_obj.type != "checkbox" && _obj.type != "radio") continue;

var id = _obj.id, name = _obj.name;
var _match = id.match(fnRE) || name.match(objRE_r) || id.match(objRE_a) ||
name.match(objRE_m) || name.match(objRE_d) || id.match(objRE);

if (!_match) continue;

var tag = _match[3], tag2 = tag+'_', guid = _match[2];
switch (tag) {
'a': aryList[tag][guid] = tag2; break;

'r', 'm', 'd':
aryList[tag][guid] = tag2 + _obj.value; break;

default :
if (_match[1]=='functor_') {
functorListEx.append(guid, ";")
}
else { // for _match[1]=='object_'
aryObjList.push(guid)
}
}
}

// further process to build objectListEx from the intermediate arrays
for (var i=0, imax=aryObjList.length; i<imax; i++) {
var id = aryObjList[i];
var r = aryRList[id] || "";
var a = aryAList[id] || "";
var m = aryMList[id] || "";
var d = aryDList[id] || "";

objectListEx.append(id , ":" , r , ":" , a , ":" , m , ":" , d , ";");
}

七、又一处小的优化
---
刚才想了想,其实上面代码中的switch还是啰嗦了。下面做一下下小的优化:
switch (_match[1] + tag) {
'functor_undefined': functorListEx.append(guid, ";"); break;

'object_undefined': aryObjList.push(guid); break;

'object_a': aryList[tag][guid] =tag2; break;

default: // for r,m,d
aryList[tag][guid] =tag2+ _obj.value;
}

分享到:
评论

相关推荐

    JavaScript代码优化一例.pdf

    "JavaScript代码优化一例" 本文主要讨论JavaScript代码的优化,着重于介绍JavaScript代码在企业开发中的重要性及其优化方法。 一、JavaScript代码的重要性 随着Web 2.0和Ajax概念的提出,JavaScript代码得到了...

    javascript网页特效编程百例源代码

    《JavaScript网页特效编程百例源代码》是一份深入实践JavaScript技术的宝贵资源,它涵盖了网页设计中的多个关键领域,包括按钮、菜单、窗体、多媒体、警告、时间、鼠标、图片、文字以及系统等特效。这份资料通过丰富...

    javascript时尚编程百例(pdg)

    总的来说,"JavaScript时尚编程百例"是一本全面而实用的指南,无论你是初学者还是经验丰富的开发者,都能从中受益匪浅。通过书中的实例,你可以深入理解JavaScript的各个方面,并将这些知识应用到实际项目中,提升你...

    SEO 网站优化 源代码的优化案例

    在SEO(搜索引擎优化)领域,源代码优化是提高网站排名和可访问性的重要环节。本文将深入探讨如何通过优化网站源代码来提升网站在...记住,源代码优化是一个持续的过程,需要定期检查和调整以适应搜索引擎算法的变化。

    javascript 400 常用 实例 特效 源代码

    通过阅读和理解代码,可以深入理解JavaScript的语法和编程思想,同时学习到如何调试和优化代码。 这个压缩包是学习和提升JavaScript技能的宝贵资源。无论是初学者还是经验丰富的开发者,都能从中受益,通过实践这些...

    JavaScript网页特效300例

    JavaScript,作为全球最广泛使用的客户端脚本语言,是构建动态、交互性网页的关键技术。"JavaScript网页特效300例" 提供了...因此,"JavaScript网页特效300例"是一个非常宝贵的参考资料,值得广大Web开发者收藏和研究。

    JavaScript网页设计300例

    - 虽然《JavaScript网页设计300例》可能主要关注原生JavaScript,但了解React、Vue或Angular等流行前端框架的基本概念和应用也是必要的,这些框架极大地提高了开发效率和代码质量。 通过本书的300个实例,读者可以...

    JavaScript无缝滚动小例

    在JavaScript代码中,我们可能会看到以下关键部分: 1. **事件监听**:通过监听窗口的`resize`和`scroll`事件,可以确保滚动效果在不同屏幕尺寸和用户滚动时依然保持平滑。 2. **速度控制**:为了实现“无缝”效果...

    JavaScript效果300例

    - 学习如何优化JavaScript代码,减少内存占用,提升网页加载速度。 总之,"JavaScript效果300例"是一个全面且实用的学习资源,它不仅让你掌握JavaScript的基本语法,还能让你了解和实践各种网页效果的实现,是提升...

    JavaScript网页设计300例.chm

    《JavaScript网页设计300例》是一本针对初学者和进阶者的JavaScript编程实践书籍,主要涵盖了大量的实际应用示例,旨在帮助读者深入理解和掌握JavaScript在网页设计中的各种技巧和方法。这本书以CHM(Compiled Help ...

    JavaScript网页设计300例.rar

    11. **性能优化**:了解如何避免全局作用域污染,减少DOM操作,使用事件委托,优化循环结构,以及利用缓存等技巧,提升JavaScript代码的运行效率。 12. **浏览器兼容性**:由于不同浏览器对JavaScript的支持程度...

    javascript页面特效38例

    4. **滚动效果**:比如滚动监听、滚动加载、滚动定位等,这些都是通过JavaScript实现的,它们可以优化页面滚动体验,如平滑滚动、视差滚动等。 5. **动画效果**:JavaScript库如jQuery提供了大量的动画函数,可以让...

    js代码优化的小示例

    本文将通过一个关于获取当前日期星期并转换为特定字符表示的例子来展示如何对JavaScript代码进行优化。 #### 原始代码 原始代码实现了一个功能:根据当前日期的星期几(0-6,分别代表周日到周六),将其转换为特定...

    突破Javascript编程实例50例

    "突破Javascript编程实例50例"是一份旨在帮助开发者提升技能、拓展思维的资源。通过一系列具体的实例,它涵盖了JavaScript的基础和高级概念,帮助你理解并运用到实际项目中去。下面,我们将详细探讨其中可能涉及的...

Global site tag (gtag.js) - Google Analytics