憨厚生

          ----Java's Slave----
          ***Java's Host***

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            165 隨筆 :: 17 文章 :: 90 評(píng)論 :: 0 Trackbacks
          我google一下,已有人翻譯了此文.比我翻譯的要好!是譯言站翻譯的
          見(jiàn)url: http://www.yeeyan.com/articles/view/92135/47626/dz
          原文見(jiàn):http://code.google.com/intl/zh-CN/speed/articles/optimizing-javascript.html

          不合適的地方,請(qǐng)大家指出來(lái)!希望對(duì)你有用!

                                                                      優(yōu)化JavaScript代碼(Optimizing JavaScript code)
              客戶端腳本讓你的應(yīng)用程序更動(dòng)態(tài),但是瀏覽器解釋腳本會(huì)帶來(lái)低效率,不同客戶端的性能也是不同的.下面我們討論一些技巧和最好的實(shí)踐來(lái)優(yōu)化你的JavaScript代碼
              使用字符串(working with string)
              String連接會(huì)給IE6和IE7垃圾回收造成影響.盡管這些問(wèn)題已經(jīng)得到在IE8解決--字符串連接的效率在IE8和其它非IE瀏覽器(如chrome)上有稍微提高.如果你的一大部分用戶群體在使用IE6,7,你應(yīng)該備加注意String的構(gòu)造方式.
              看一下如下例子:
              

          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來(lái)代替連接:
              

           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

              
              同樣的,在循環(huán)和/或條件語(yǔ)句中通過(guò)連接來(lái)構(gòu)造字符串也是非常低效的.下面是一個(gè)錯(cuò)誤的例子:
             

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

             

              通過(guò)助手函數(shù)生成字符串(Building strings with portions coming from helper functions)
              通過(guò)把字符串生成器傳遞到函數(shù)中來(lái)構(gòu)造一個(gè)長(zhǎng)字符串,要避免臨時(shí)的String結(jié)果.
              例如,假設(shè)函數(shù)buildMenuItemHtml_ 需要用文字串(literal)和變量來(lái)構(gòu)造String,并在內(nèi)部使用了String構(gòu)造器.而不是如下方式使用:

               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對(duì)象,就會(huì)為其生成一個(gè)方法和閉包.

            baz.Bar = function() {
            
          // 構(gòu)造函數(shù), constructor body
            this.foo = function() {
            
          // 方法,method body
            }
          ;
           }


           推薦方式是:

           baz.Bar = function() {
            
          // 構(gòu)造函數(shù),constructor body
           }
          ;

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


           這種方式,不管有多少個(gè)baz.Bar對(duì)象生成,僅僅只建立一個(gè)方法foo且沒(méi)有產(chǎn)生閉包.
           初始化實(shí)例變量(Initializing instance variables)
           在原型(prototype)上用值類型[value type](而不是引用類型[reference type])聲明或初始化實(shí)例變量.這避免了在每次調(diào)用構(gòu)造函數(shù)時(shí)運(yùn)行不必要的初始化代碼.(有些情況下是不能這樣做的:實(shí)例變量的初始值依賴于構(gòu)造參數(shù)或是在構(gòu)造時(shí)的其它狀態(tài)的變量(some other state at time of construction))
           例子:

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


          推薦的寫(xiě)法:

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


           避開(kāi)閉包的陷阱(Avoiding pitfalls with closures)

           閉包是JavaScript的一個(gè)強(qiáng)大且有用的特色;但是它有幾個(gè)缺點(diǎn):
           1,它們是常見(jiàn)的內(nèi)存泄漏源
           2,生成閉包明顯的比生成不是閉包的內(nèi)部函數(shù)慢,比調(diào)用靜態(tài)函數(shù)更慢.例如

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


           上面比下面的寫(xiě)法要慢:(上面的代碼產(chǎn)生了閉包)

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


           上面比下面的寫(xiě)法要慢:

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


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


          3,它們?cè)黾恿俗兞康淖饔糜?scope chain)的層次.當(dāng)瀏覽器解析屬性的時(shí)候,將會(huì)檢查所有層次的作用域.見(jiàn)下面的例子:

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


          var f = createFunctionWithClosure();
          f(); 


          當(dāng)執(zhí)行f方法的時(shí)候,引用a比引用b慢,引用b比引用c慢.
          IE中閉包更多信息可以查看 IE+JScript Performance Recommendations Part 3: JavaScript Code inefficiencies
          避免用with(Avoiding with)
           在你代碼中避免用with.它對(duì)性能有負(fù)面影響,因?yàn)樗薷牧俗饔糜?在其它作用域查找變量的開(kāi)銷很大.
          避免瀏覽器的內(nèi)存泄露(Avoiding browser memory leaks)
          內(nèi)存泄露是web應(yīng)用程序普遍存在的問(wèn)題,它會(huì)產(chǎn)生巨大的性能危害(hit).隨著瀏覽器內(nèi)存使用增加,你的web應(yīng)用程序,用戶系統(tǒng)其它部分操作,將變的慢起來(lái).大部分web應(yīng)用程序的內(nèi)存泄露是因?yàn)樵?nbsp;JavaScript腳本和Dom之間生成了循環(huán)引用(例如:javascript腳本和IE com結(jié)構(gòu)之間,javascript腳本和Firefox xpcom結(jié)構(gòu)之間)
           下面是避免內(nèi)存泄漏一些經(jīng)驗(yàn)法則:
           使用事件系統(tǒng)關(guān)聯(lián)事件處理函數(shù)(Use an event system for attaching event handlers)
           大部分的循環(huán)引用模式[DOM 元素-->事件處理函數(shù)(event handler)-->閉包(closure scope)-->DOM元素].為了避免這個(gè)問(wèn)題,可以用經(jīng)過(guò)充分測(cè)試事件系統(tǒng)(event system)來(lái)關(guān)聯(lián)事件處理函數(shù)(event handlers),例如:Google doctype,Dojo,JQuery
           另外,在IE中使用用內(nèi)聯(lián)事件函數(shù)(inline event handlers)會(huì)導(dǎo)致另一種的類型的泄露.這不是通常的循環(huán)引用類型的泄露,而是由內(nèi)部臨時(shí)匿名腳本對(duì)象產(chǎn)生的泄露.詳細(xì)信息,請(qǐng)看文章"DOM insertin Order Leak Model"和例子JavaScript Kit tutorial.
           避免擴(kuò)展(expando)屬性
           擴(kuò)展(expando)屬性是把任意JavaScript的屬性附加的到DOM元素上,這是循環(huán)引用產(chǎn)生的根源.你可以不產(chǎn)生內(nèi)存泄露來(lái)擴(kuò)展(expando)屬性,但是這是很容易產(chǎn)生內(nèi)存泄露的.泄露模式是[DOM元素-->擴(kuò)展(via expando)-->中間對(duì)象(intermediary object)-->DOM元素].最好是避免使用用它們.如果你用到它們,僅可使用原始類型(primitive types)作為值.如果不是原始類型,當(dāng)擴(kuò)展(expando)屬性不在使用的時(shí)候,要把它置為空.可以參考文章"Circular References"
           

          posted on 2009-12-14 21:43 二胡 閱讀(1933) 評(píng)論(0)  編輯  收藏 所屬分類: JS翻譯
          主站蜘蛛池模板: 筠连县| 定兴县| 石屏县| 大埔县| 灌南县| 葵青区| 黄浦区| 休宁县| 双牌县| 喀什市| 馆陶县| 湖北省| 南岸区| 鲜城| 饶河县| 漾濞| 文成县| 清涧县| 鲜城| 友谊县| 鄂尔多斯市| 桃江县| 洪江市| 铜鼓县| 铁力市| 巧家县| 安吉县| 华坪县| 尚义县| 贺兰县| 石泉县| 金门县| 军事| 钟祥市| 门头沟区| 廉江市| 温泉县| 徐汇区| 全南县| 赣州市| 韶山市|