JavaScript 代码优化(译)
Contents
https://developers.google.com/speed/articles/optimizing-javascript
作者: Gregory Baker, Software Engineer on GMail & Erik Arvidsson, Software Engineer on Google Chrome
不要在constructor中定义类方法,应该使用原型。
下面的代码会在每次构造baz.Bar
实例时,创建一个新的function实例;随着foo创建的同时还创建了一个闭包:
baz.Bar = function() { |
推荐下面的方式
baz.Bar = function() { |
无论创建多少baz.Bar
实例,只有一个foo
function被创建,同时避免了闭包。
在prototype上申明、初始化数值型的实例变量的初始值
数值型:比如:number, Boolean, null, undefined, or string
引用型:略
避免了构造时,每次都调用无用的初始化代码。(与构造函数参数相关的实例变量除外)
举个例子:
foo.Bar = function() { |
可以改为
foo.Bar = function() { |
回避闭包带来的缺陷
闭包是JavaScript语言强大且有用的特性;然而同时也存在着许多缺陷:
- 内存泄露是闭包最常见的缺点。
- 创建闭包比创建
inner function
更慢,而inner function
又慢于static function
。
举例:
function setupAlertTimeout() { |
慢于下面代码:
function setupAlertTimeout() { |
而上述代码又慢于下面代码:
function alertMsg() { |
- 闭包增加了语义链的层级,浏览器在resolves属性时,每一层的语义链都会被检查 :
var a = 'a'; |
当调用f
时,referencing 效率:
a < b < c |
参考 IE+JScript Performance Recommendations Part 3: JavaScript Code inefficiencies 了解 IE 下的闭包.
避免使用 with
避免使用 with
,它不仅影响效率,还修改了scope chain,导致查找变量的开销变得更加昂贵。
避免浏览器内存泄露
内存泄露在 web 应用中太常见了,而且会引起严重的性能问题。
最常见的内存泄露是JavaScript引擎和浏览器C++ DOM对象(比如IE COM 基础组件,Firefox XPCOM 基础组件)循环引用
Use an event system for attaching event handlers
一种最常见的循环引用模式:
[ DOM element --> event handler --> closure scope --> DOM element] |
参考 MSDN blog post.
要想避免这种情况,可以使用 Google doctype, Dojo, or JQuery等成熟的事件处绑定库。
另外在 IE 中使用inline event handlers 会造成另外一种泄露,不同于普通的循环引用,泄露的是一种内部零时匿名script对象。
详情可参考 Understanding and Solving Internet Explorer Leak Patterns “DOM Insertion Order Leak Model” 章节。
具体例子 JavaScript Kit tutorial.
避免 expando properties
Expando properties are properties added to DOM nodes with JavaScript, where those properties are not part of the object’s DOM specification:
通过dot访问一个不存在的DOM属性时,javascript会自动创建一个Expando properties。
这种行为通常导致循环引用。
[ DOM element --> via expando--> intermediary object --> DOM element ] |
// First set up the script scope to element reference |
最佳实践是不用使用。如果非要用这种特性不可,仅仅访问 primitive类型
var div = document.getElementsByTagName('div')[0]; |
或者将expando property置为null。
document.getElementById("LeakedDiv").expandoProperty = |
参考 Understanding and Solving Internet Explorer Leak Patterns"Circular References" 章节。
Author: deskid
Link: https://deskid.github.io/2017/11/27/JavaScript-代码优化/
License: 知识共享署名-非商业性使用 4.0 国际许可协议