[翻譯]High Performance JavaScript(008)

Nested Members  嵌套成員

 

    Since object members may contain other members, it's not uncommon to see patterns such as window.location.href in JavaScript code. These nested members cause the JavaScript engine to go through the object member resolution process each time a dot is encountered. Figure 2-12 shows the relationship between object member depth and time to access.

    由於對象成員可能包含其它成員,例如不太常見的寫法window.location.href這種模式。每遇到一個點號,JavaScript引擎就要在對象成員上執行一次解析過程。圖2-12顯示出對象成員深度與訪問時間的關係。

Figure 2-12. Access time related to property depth

圖2-12  訪問時間與屬性深度的關係

 

    It should come as no surprise, then, that the deeper the nested member, the slower the data is accessed. Evaluating location.href is always faster than window.location.href, which is faster than window.location.href.toString(). If these properties aren't on the object instances, then member resolution will take longer as the prototype chain is searched at each point.

    結果並不奇怪,成員嵌套越深,訪問速度越慢。location.href總是快於window.location.href,而後者也要比window.location.href.toString()更快。如果這些屬性不是對象的實例屬性,那麼成員解析還要在每個點上搜索原形鏈,這將需要更長時間。

 

Caching Object Member Values  緩存對象成員的值

 

    With all of the performance issues related to object members, it's easy to believe that they should be avoided whenever possible. To be more accurate, you should be careful to use object member only when necessary. For instance, there's no reason to read the value of an object member more than once in a single function:

    由於所有這些性能問題與對象成員有關,所以如果可能的話請避免使用它們。更確切地說,你應當小心地,只在必要情況下使用對象成員。例如,沒有理由在一個函數中多次讀取同一個對象成員的值:

 

function hasEitherClass(element, className1, className2){
  return element.className == className1 || element.className == className2;
}

    In this code, element.className is accessed twice. Clearly this value isn't going to change during the course of the function, yet there are still two object member lookups performed. You can eliminate one property lookup by storing the value in a local variable and using that instead:

    在此代碼中,element.className被訪問了兩次。很明顯,在這個函數過程中它的值是不會改變的,但仍然引起兩次對象成員搜索過程。你可以將它的值存入一個局部變量,消除一次搜索過程。修改如下:

 

function hasEitherClass(element, className1, className2){
  var currentClassName = element.className;
  return currentClassName == className1 || currentClassName == className2;
}

    This rewritten version of the function limits the number of member lookups to one. Since both member lookups were reading the property's value, it makes sense to read the value once and store it in a local variable. That local variable then is much faster to access.

    此重寫後的版本中成員搜索只進行了一次。既然兩次對象搜索都在讀屬性值,所以有理由只讀一次並將值存入局部變量中。局部變量的訪問速度要快得多。

 

    Generally speaking, if you're going to read an object property more than one time in a function, it's best to store that property value in a local variable. The local variable can then be used in place of the property to avoid the performance overhead of another property lookup. This is especially important when dealing with nested object members that have a more dramatic effect on execution speed.

    一般來說,如果在同一個函數中你要多次讀取同一個對象屬性,最好將它存入一個局部變量。以局部變量替代屬性,避免多餘的屬性查找帶來性能開銷。在處理嵌套對象成員時這點特別重要,它們會對運行速度產生難以置信的影響。

 

    JavaScript namespacing, such as the technique used in YUI, is a source of frequently accessed nested properties. For example:

    JavaScript的命名空間,如YUI所使用的技術,是經常訪問嵌套屬性的來源之一。例如:

 

function toggle(element){
  if (YAHOO.util.Dom.hasClass(element, "selected")){
    YAHOO.util.Dom.removeClass(element, "selected");
    return false;
  } else {
    YAHOO.util.Dom.addClass(element, "selected");
    return true;
  }
}

    This code repeats YAHOO.util.Dom three times to access three different methods. For each method there are three member lookups, for a total of nine, making this code quite inefficient. A better approach is to store YAHOO.util.Dom in a local variable and then access that local variable:

    此代碼重複YAHOO.util.Dom三次以獲得三種不同的方法。每個方法都產生三次成員搜索過程,總共九次,導致此代碼相當低效。一個更好的方法是將YAHOO.util.Dom存儲在局部變量中,然後訪問局部變量:

 

function toggle(element){
  var Dom = YAHOO.util.Dom;
  if (Dom.hasClass(element, "selected")){
    Dom.removeClass(element, "selected");
    return false;
  } else {
    Dom.addClass(element, "selected");
    return true;
  }
}

    The total number of member lookups in this code has been reduced from nine to five. You should never look up an object member more than once within a single function, unless the value may have changed.

    總的成員搜索次數從九次減少到五次。在一個函數中,你絕不應該對一個對象成員進行超過一次搜索,除非該值可能改變。

 

Summary  總結

 

    Where you store and access data in JavaScript can have a measurable impact on the overall performance of your code. There are four places to access data from: literal values, variables, array items, and object members. These locations all have different performance considerations.

    在JavaScript中,數據存儲位置可以對代碼整體性能產生重要影響。有四種數據訪問類型:直接量,變量,數組項,對象成員。它們有不同的性能考慮。

 

• Literal values and local variables can be accessed very quickly, whereas array items and object members take longer.

直接量和局部變量訪問速度非常快,數組項和對象成員需要更長時間。


• Local variables are faster to access than out-of-scope variables because they exist in the first variable object of the scope chain. The further into the scope chain a variable is, the longer it takes to access. Global variables are always the slowest to access because they are always last in the scope chain.

局部變量比域外變量快,因爲它位於作用域鏈的第一個對象中。變量在作用域鏈中的位置越深,訪問所需的時間就越長。全局變量總是最慢的,因爲它們總是位於作用域鏈的最後一環。


• Avoid the with statement because it augments the execution context scope chain. Also, be careful with the catch clause of a try-catch statement because it has the same effect.

避免使用with表達式,因爲它改變了運行期上下文的作用域鏈。而且應當小心對待try-catch表達式的catch子句,因爲它具有同樣效果。


• Nested object members incur significant performance impact and should be minimized.

嵌套對象成員會造成重大性能影響,儘量少用。


• The deeper into the prototype chain that a property or method exists, the slower it is to access.

一個屬性或方法在原形鏈中的位置越深,訪問它的速度就越慢。


• Generally speaking, you can improve the performance of JavaScript code by storing frequently used object members, array items, and out-of-scope variables in local variables. You can then access the local variables faster than the originals.

 

一般來說,你可以通過這種方法提高JavaScript代碼的性能:將經常使用的對象成員,數組項,和域外變量存入局部變量中。然後,訪問局部變量的速度會快於那些原始變量。

 

    By using these strategies, you can greatly improve the perceived performance of a web application that requires a large amount of JavaScript code.

    通過使用這些策略,你可以極大地提高那些需要大量JavaScript代碼的網頁應用的實際性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章