优化JavaScript代码
见www.yeeyan.com/articles/view/92135/47626/dz
原文见:http://code.google.com/intl/zh-CN/speed/articles/optimizing-javascript.html
不合适的地方,请大家指出来!希望对你有用!
优化JavaScript代码(Optimizing JavaScript code)
客户端脚本让你的应用程序更动态,但是浏览器解释脚本会带来低效率,不同客户端的性能也是不同的.下面我们讨论一些技巧和最好的实践来优化你的JavaScript代码
使用字符串(working with string)
String连接会给IE6和IE7垃圾回收造成影响.尽管这些问题已经得到在IE8解决--字符串连接的效率在IE8和其它非IE浏览器(如chrome)上有稍微提高.如果你的一大部分用户群体在使用IE6,7,你应该备加注意String的构造方式.
看一下如下例子:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
尝试用join来代替连接:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
2
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
3
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
4
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
5
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
6
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
7
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
8
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
9
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
10
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
同样的,在循环和/或条件语句中通过连接来构造字符串也是非常低效的.下面是一个错误的例子:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
正确的方式如下:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
通过助手函数生成字符串(Building strings with portions coming from helper functions)
通过把字符串生成器传递到函数中来构造一个长字符串,要避免临时的String结果.
例如,假设函数buildMenuItemHtml_ 需要用文字串(literal)和变量来构造String,并在内部使用了String构造器.而不是如下方式使用:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
推荐如下方式:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
定义类方法(Defining class methods)
下面的代码是低效率的,每生成一次baz.Bar对象,就会为其生成一个方法和闭包.
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
推荐方式是:
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
这种方式,不管有多少个baz.Bar对象生成,仅仅只建立一个方法foo且没有产生闭包.
初始化实例变量(Initializing instance variables)
在原型(prototype)上用值类型[value type](而不是引用类型[reference type])声明或初始化实例变量.这避免了在每次调用构造函数时运行不必要的初始化代码.(有些情况下是不能这样做的:实例变量的初始值依赖于构造参数或是在构造时的其它状态的变量(some other state at time of construction))
例子:
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
推荐的写法:
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
避开闭包的陷阱(Avoiding pitfalls with closures)
闭包是JavaScript的一个强大且有用的特色;但是它有几个缺点:
1,它们是常见的内存泄漏源
2,生成闭包明显的比生成不是闭包的内部函数慢,比调用静态函数更慢.例如
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
上面比下面的写法要慢:(上面的代码产生了闭包)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
上面比下面的写法要慢:
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
3,它们增加了变量的作用域(scope chain)的层次.当浏览器解析属性的时候,将会检查所有层次的作用域.见下面的例子:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://www.blogjava.net/Images/dot.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
当执行f方法的时候,引用a比引用b慢,引用b比引用c慢.
IE中闭包更多信息可以查看 IE+JScript Performance Recommendations Part 3: JavaScript Code inefficiencies
避免用with(Avoiding with)
在你代码中避免用with.它对性能有负面影响,因为它修改了作用域,在其它作用域查找变量的开销很大.
避免浏览器的内存泄露(Avoiding browser memory leaks)
内存泄露是web应用程序普遍存在的问题,它会产生巨大的性能危害(hit).随着浏览器内存使用增加,你的web应用程序,用户系统其它部分操作,将变的慢起来.大部分web应用程序的内存泄露是因为在 JavaScript脚本和Dom之间生成了循环引用(例如:javascript脚本和IE com结构之间,javascript脚本和Firefox xpcom结构之间)
下面是避免内存泄漏一些经验法则:
使用事件系统关联事件处理函数(Use an event system for attaching event handlers)
大部分的循环引用模式[DOM 元素-->事件处理函数(event handler)-->闭包(closure scope)-->DOM元素].为了避免这个问题,可以用经过充分测试事件系统(event system)来关联事件处理函数(event handlers),例如:Google doctype,Dojo,JQuery
另外,在IE中使用用内联事件函数(inline event handlers)会导致另一种的类型的泄露.这不是通常的循环引用类型的泄露,而是由内部临时匿名脚本对象产生的泄露.详细信息,请看文章"DOM insertin Order Leak Model"和例子JavaScript Kit tutorial.
避免扩展(expando)属性
扩展(expando)属性是把任意JavaScript的属性附加的到DOM元素上,这是循环引用产生的根源.你可以不产生内存泄露来扩展(expando)属性,但是这是很容易产生内存泄露的.泄露模式是[DOM元素-->扩展(via expando)-->中间对象(intermediary object)-->DOM元素].最好是避免使用用它们.如果你用到它们,仅可使用原始类型(primitive types)作为值.如果不是原始类型,当扩展(expando)属性不在使用的时候,要把它置为空.可以参考文章"Circular References"
转载于:https://www.cnblogs.com/EricGu/archive/2009/12/15/1624775.html
优化JavaScript代码相关推荐
- 优化javaScript代码,提高执行效率
今天看完书,总结了一下可以如何优化 JavaScript . 1.合并js文件 为优化性能,可以把多个js文件(css文件也可以)合并成极少数大文件.跟十个5k的js文件相比,合并成一个50k的文件更 ...
- 翻译-高质量JavaScript代码书写基本要点(转载)
by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpress/?p=1173 原文作者:S ...
- 如何优雅的编写 JavaScript 代码
几乎每个大一点公司都有一个"运行时间长,维护的工程师换了一批又一批"的项目,如果参与到这样的项目中来,大部分人只有一个感觉--"climb the shit mounta ...
- JavaScript: 代码简洁之道
一.变量 1.用有意义且常用的单词命名变量 Bad: const yyyymmdstr = moment().format('YYYY/MM/DD'); Good: const currentDate ...
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
才华横溢的Stoyan Stefanov,在他写的由O'Reilly初版的新书<JavaScript Patterns>(JavaScript模式)中,我想要是为我们的读者贡献其摘要,那会 ...
- 第一百一十八期:运行 JavaScript 代码片段的 20 种工具
运行 JavaScript 代码片段的 20 种工具 前端日常开发中,我们使用喜爱的 IDE 调试 JavaScript 代码,比如我喜欢的代码编辑器有两个,Sublime Text 3 和 VS C ...
- 增强优化JavaScript性能的方法 - 技巧大全
一.优化页面加载时间 在修改JavaScript代码提升网页或应用程序的性能之前,我们先了解一下客户端与JavaScript代码之间的交互处理: JavaScript代码通过HTML的<scri ...
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点(转)
才华横溢的Stoyan Stefanov,在他写的由O'Reilly初版的新书<JavaScript Patterns>(JavaScript模式)中,我想要是为我们的读者贡献其摘要,那会 ...
- vue 代码快捷键_你可能不知道的19种运行JavaScript代码工具
前端日常开发中,我们使用喜爱的 IDE 调试 JavaScript 代码,比如我喜欢的代码编辑器有两个,Sublime Text 3 和 VS Code,前几年还使用过 Atom,偶尔我们会遇到临时需 ...
最新文章
- 用数据分析《你好,李焕英》“斐妈”爆红的真相
- vrrp的组播地址是多少
- 阿里云Centos系统使用密钥对登陆
- centos 7 构造iptables开放80port
- linux主机load average的概念计算过程注意事项
- CRM product ID format相关配置
- u6系统服务器启动不了,u6链接不到服务器
- php改密后joomla无法登陆,php – Joomla 3.3禁用“重置密码”功能
- 塞尔达传说雷电大剑位置_《塞尔达传说:荒野之息》全收集——双手武器(1)...
- 混合列压缩(HCC)在OLAP及OLTP场景中的测试
- 我的所有邮箱 My all E-mail
- sklearn.metrics.roc_curve使用说明
- css移动端页面单位,视窗单位在移动端上的使用技巧
- CSDN认证博客专家申请通过,感动,欣慰,分享一下我的经验!
- 90后美女学霸传奇人生:出身清华姚班,成斯坦福AI实验室负责人高徒
- 计算机主机组件图,电脑主机结构图大全
- Stolz定理 【补充知识】Stolz(斯托尔茨)定理(详解➕例题)
- aspnetpager 详解
- 全概率公式和贝叶斯公式(转载)
- 中国(成都)区块链博物馆为区块链正名
热门文章
- python条形图间距-Python-Matplotlib 5 条形图
- python stm32-python学习(一)
- python下载后如何使用-如何使用Python通过HTTP下载文件
- python3官方文档 中文-Python 3.7 官方文档中文翻译召集
- python语音在线编辑-Python如何实现文本转语音
- python怎么读文件夹下的文件夹-python如何获取当前文件夹下所有文件名详解
- 在python中、下列代码的输出是什么-Python 面试中 8 个必考问题
- Git Bash命令行基础
- javascript高级程序设计之函数表达式
- mybatis中sqlSession的设计与实现