Best practices for reducing Garbage Collector activity in Javascript
原则 尽量减少创建(creating)与销毁(destroying)的过程
常见的创建过程
- 使用
new
或者[]
,{}
- 连接字符时
str.concat()
- 进入一个有函数定义的作用域
- 进入错误
catch
阶段 - 使用一个匿名函数时
(function(){...})
- 转换对象时
Object(number)
,Number.prototype.toString.call(42)
- 调用内置对象
prototype
方法时Array.prototype.slice
- 使用
arguments
来获取函数参数时 - 使用正则表达式来匹配或替换字符串时
优化建议
使用对象池或者重用组件
- 将子作用域的函数提到更高级的作用域,匿名函数也可以算作这一类。在
closure compiler
会自动创建inline函数
function loopfunc()
{
//do something
}
while(true)
{
$.each(listofthings, loopfunc);
options.ChangingVariable = newvalue;
someOtherFunction(options);
}
将快于
while(true)
{
$.each(listofthings, function(){
//do something on the list
});
someOtherFunction({
var1: value1,
var2: value2,
ChangingVariable: newvalue
});
}
- 尽量不要使用字符串于
key
和dynamic addr
lookupTable[
foo+x]
和document.getElementById('foo-' + x)
两者都包含了字符串的创建.在很多情况下,你都可以将keys
绑定到生命周期长的引用上,而非每次使用时,都重新创建它。根据浏览器,你可以考虑使用Map类
避免频繁的
split
调用和正则匹配将
exception catch
替换为if-else
try { op(x) } catch (e) { ... }
转换为
if (!opCouldFailOn(x)) { op(x); } else { ... }
如果你不能避免创建字符串, 比如向服务器发送消息时,那么你可以使用内置的
JSON.stringify
。JSON.stringify
使用内置的buffer
来收集内容,而非为它们分配内存尽量不要频繁地调用匿名函数,这通常指某些高频率调用的回调函数。对于这种情况,尽可能的在外部作用域声明回调函数,而不是使用匿名函数形式
避免使用
arguments
,因为每次使用arguments
,都要创建一个类似于Array
的对象