打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
优化JavaScript代码的几点建议

 客户端脚本能够使得应用更加具有吸引力,但是浏览器对脚本代码的解释执行可能也会导致效率低下。

   这里我们探讨几个优化JavaScript代码的最佳实践建议。

 

1、处理字符串

      字符串拼接在IE 6、7下的垃圾回收性能很差。虽然IE 8已经解决了这个问题。如果你的用户中有相当一部分人使用IE 6、7,那么你得谨慎构建你的字符串了。     

      比如这个例子:

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:

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();

      类似的,在条件分支语句或循环语句中使用字符串拼接也很低效。不好的做法:

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('');

 

2、使用helper functions构建字符串片段

      通过将string builder传入helper function来避免临时存储消耗。

      例如不该用下面这种:

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();

 

3、定义类方法

     下面的代码是低效的,因为每次有一个baz.Bar实例被创建,一个新的函数和闭包就为foo创建:

baz.Bar = function() {  // constructor body  this.foo = function() {  // method body  };}

       更优的做法是:

baz.Bar = function() {  // constructor body};baz.Bar.prototype.foo = function() {  // method body};

       通过这种方法,不管有多少个baz.Bar实例被创建,只有一个function被创建,并且也不形成闭包。

 

4、初始化实例变量

      将实例变量的声明/初始化放到prototype中,如果实例变量带有一个值类型的初始值(即number、Boolean、null、undefined或字符串类型值)。这避免了每次构造器创建时都运行毫无意义的初始化代码。

      不好的做法:

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';

 

5、避免闭包中的陷阱

      闭包是一个强大有用的东西。但是他们有一些缺点,包括:

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);}

      闭包增加了一层作用域链。当浏览器解析属性时,每一层的作用域链都必须被检查。在下面的例子:

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+JScript Performance Recommendations Part 3: JavaScript Code inefficiencies 来获取更多在IE下正确使用闭包的信息

 

6、避免with

      避免在代码中使用with语句。它对性能产生负面影响,因为它改变了作用域链,使得在其它作用域中查找变量的代价更加昂贵。

 

7、避免浏览器内存泄露

      内存泄露是web应用中的常见问题,会导致巨大的性能问题。当浏览器消耗的内存增加,你的其他Web应用以及用户系统的其他程序都会变得很慢。最常见的内存泄露场景是JavaScript引擎和浏览器的DOM对象的循环依赖,比如下面这个例子:

<script language='javascript'>   var menu = document.getElementById('myMenu');   AttachEvent(menu);   function AttachEvent(element) {      element.attachEvent( "onmouseover", mouseHandler);      function mouseHandler(){ /* whatever */ }   }</script>
       又比如下面的代码:
var myGlobalObject;function SetupLeak(){   //Here a reference created from the JS World     //to the DOM world.    myGlobalObject=document.getElementById("LeakedDiv");    //Here DOM refers back to JS World;     //hence a circular reference.    //The memory will leak if not handled properly.    document.getElementById("LeakedDiv").expandoProperty = myGlobalObject;}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
kangax 的javascript谜题
js的最好写法(转)
jQuery学习笔记之JavaScript基础语法篇
深入理解javascript作用域系列第二篇
谈"this"
深入详解javascript之delete操作符
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服