惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Simon Willison's Weblog
Simon Willison's Weblog
P
Privacy International News Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
Troy Hunt's Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Attack and Defense Labs
Attack and Defense Labs
S
Secure Thoughts
V2EX - 技术
V2EX - 技术
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
O
OpenAI News
Cloudbric
Cloudbric
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Help Net Security
Help Net Security
Cyberwarzone
Cyberwarzone
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Spread Privacy
Spread Privacy
NISL@THU
NISL@THU
N
News and Events Feed by Topic
T
Tenable Blog
S
Security @ Cisco Blogs
N
News and Events Feed by Topic
The Hacker News
The Hacker News
C
CXSECURITY Database RSS Feed - CXSecurity.com
宝玉的分享
宝玉的分享
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google DeepMind News
Google DeepMind News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
V
Visual Studio Blog
P
Proofpoint News Feed
Webroot Blog
Webroot Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 三生石上(FineUI控件)
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Jina AI
Jina AI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
L
LangChain Blog
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东

博客园 - EricGu

DES加密解密函数 - EricGu - 博客园 Hibernate Annotation笔记 Groovy和Grails配置方法 Log4net的用法 在vs2008中设置jquery智能提示 开发人员最喜爱的十大免费的Visual Studio插件 Velocity快速指南 配置nhibernate时报 No persister for: NH.Model.Entities.Customer 异常 - EricGu 解决UpdatePanle中执行后台时间密码域丢失问题 网页制作技巧收集 Virtual PC 2007 SP1虚拟机上安装Ubuntu 9.04桌面版 JavaScript && CSS / CSS中的点滴 oracle10g中的5个服务的作用 ORACLE服务的作用 关于TreeView控件发布后无法显示展开图标的问题 怎样设计网页安全字体 Div+CSS网页制作误区 未来五年程序员应当具备的十项技能 标准W3C盒子模型
优化JavaScript代码
EricGu · 2009-12-15 · via 博客园 - EricGu

我google一下,已有人翻译了此文.感觉比我翻译的要好!是译言站翻译的
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的构造方式.
    看一下如下例子:
    

var veryLongMessage =
    'This is a 
long string that due to our strict line length limit of' +
    maxCharsPerLine 
+
    ' characters per line must be wrapped. ' 
+
    percentWhoDislike 
+
    '
% of engineers dislike this rule. The line length limit is for ' +
    ' style purposes, but we don't want it to have a performance impact.' 
+
    ' So the question is how should we 
do the wrapping?'; 

 
    尝试用join来代替连接:
    

 1var veryLongMessage =
 2    ['This is a long string that due to our strict line length limit of',
 3    maxCharsPerLine,
 4    ' characters per line must be wrapped. ',
 5    percentWhoDislike,
 6    '% of engineers dislike this rule. The line length limit is for ',
 7    ' style purposes, but we don't want it to have a performance impact.',
 8    ' So the question is how should we do the wrapping?'
 9    ].join(); 
10

    
    同样的,在循环和/或条件语句中通过连接来构造字符串也是非常低效的.下面是一个错误的例子:
   

  var fibonacciStr = 'First 20 Fibonacci Numbers';
    
for (var i = 0; i < 20; i++{
        fibonacciStr 
+= i + ' = ' + fibonacci(i) + '';
    }
 


    正确的方式如下:
   

 var strBuilder = ['First 20 fibonacci numbers:'];
    
for (var i = 0; i < 20; i++{
      strBuilder.push(i, ' 
= ', fibonacci(i));
    }

  
var fibonacciStr = strBuilder.join(''); 

    通过助手函数生成字符串(Building strings with portions coming from helper functions)
    通过把字符串生成器传递到函数中来构造一个长字符串,要避免临时的String结果.
    例如,假设函数buildMenuItemHtml_ 需要用文字串(literal)和变量来构造String,并在内部使用了String构造器.而不是如下方式使用:

     var strBuilder = [];
   
for (var i = 0, length = menuItems.length; i < length; i++{
    strBuilder.push(
this.buildMenuItemHtml_(menuItems[i]));
  }

  
var menuHtml = strBuilder.join(); 


推荐如下方式:

 var strBuilder = [];
 
for (var i = 0, length = menuItems.length; i < length; i++{
   
this.buildMenuItem_(menuItems[i], strBuilder);
 }

 
var menuHtml = strBuilder.join(); 


  定义类方法(Defining class methods)
  下面的代码是低效率的,每生成一次baz.Bar对象,就会为其生成一个方法和闭包.

  baz.Bar = function() {
  
// 构造函数, constructor body
  this.foo = function() {
  
// 方法,method body
  }
;
 }


 推荐方式是:

 baz.Bar = function() {
  
// 构造函数,constructor body
 }
;

 baz.Bar.prototype.foo 
= function() {
  
//方法, method body
 }
;


 这种方式,不管有多少个baz.Bar对象生成,仅仅只建立一个方法foo且没有产生闭包.
 初始化实例变量(Initializing instance variables)
 在原型(prototype)上用值类型[value type](而不是引用类型[reference type])声明或初始化实例变量.这避免了在每次调用构造函数时运行不必要的初始化代码.(有些情况下是不能这样做的:实例变量的初始值依赖于构造参数或是在构造时的其它状态的变量(some other state at time of construction))
 例子:

 foo.Bar = function() {
  
this.prop1_ = 4;
  
this.prop2_ = true;
  
this.prop3_ = [];
  
this.prop4_ = 'blah';
}


推荐的写法:

foo.Bar = function() {
  
this.prop3_ = [];
}
;
foo.Bar.prototype.prop1_ 
= 4;
foo.Bar.prototype.prop2_ 
= true;
foo.Bar.prototype.prop4_ 
= 'blah';    


 避开闭包的陷阱(Avoiding pitfalls with closures)

 闭包是JavaScript的一个强大且有用的特色;但是它有几个缺点:
 1,它们是常见的内存泄漏源
 2,生成闭包明显的比生成不是闭包的内部函数慢,比调用静态函数更慢.例如

 function setupAlertTimeout() {
  
var msg = 'Message to alert';
  window.setTimeout(
function() { alert(msg); }100);
 }


 上面比下面的写法要慢:(上面的代码产生了闭包)

 function setupAlertTimeout() {
  window.setTimeout(
function() {
    
var msg = 'Message to alert';
    alert(msg);
  }
100);
 }
 


 上面比下面的写法要慢:

 function alertMsg() {
  
var msg = 'Message to alert';
  alert(msg);
}


function setupAlertTimeout() {
  window.setTimeout(alertMsg, 
100);
}
 


3,它们增加了变量的作用域(scope chain)的层次.当浏览器解析属性的时候,将会检查所有层次的作用域.见下面的例子:

var a = 'a';
function createFunctionWithClosure() {
  
var b = 'b';
  
return function () {
    
var c = 'c';
    a;
    b;
    c;
  }
;
}


var f = createFunctionWithClosure();
f(); 


当执行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"