日期:2014-05-16  浏览次数:20426 次

JavaScript Patterns 读书笔记(七)

7.Client Pattern

  • DOM Access
    ?? DOM access is expensive; it’s the most common bottleneck when it comes to JavaScript performance. This is because the DOM is usually implemented separately from the JavaScript engine. From a browser’s perspective, it makes sense to take this approach, because a JavaScript application may not need DOM at all. And also languages other than JavaScript (for example, VBScript in IE) can be used to work with the page’s DOM. The bottom line is that DOM access should be reduced to minimum. This means:

    ??? ??? ??? ? Avoiding DOM access in loops
    ??? ??? ??? ? Assigning DOM references to local variables and working with the locals
    ??? ??? ??? ? Using selectors API where available
    ??? ??? ??? ? Caching the length when iterating over HTML collections

    ?? Consider the following example where the second (better) loop, despite being longer, will be tens to hundreds of times faster, depending on the browser:
    // antipattern
    for (var i = 0; i < 100; i += 1) {
    	document.getElementById("result").innerHTML += i + ", ";
    }
    
    // better - update a local variable
    var i, content = "";
    for (i = 0; i < 100; i += 1) {
    	content += i + ",";
    }
    document.getElementById("result").innerHTML += content;
    
    ? ? In the next snippet, the second example (using a local variable style) is better, although it requires one more line of code and one more variable:
    // antipattern
    var padding = document.getElementById("result").style.padding,
    margin = document.getElementById("result").style.margin;
    
    // better
    var style = document.getElementById("result").style,
    padding = style.padding,
    margin = style.margin;
    
    ?
    ?? Using selector APIs means using the methods:
    ??
    document.querySelector("ul .selected");
    document.querySelectorAll("#widget .class");
    ?? These methods accept a CSS selector string and return a list of DOM nodes that match the selection. The selector methods are available in modern browsers (and in IE since version 8) and will always be faster than if you do the selection yourself using other DOM methods. Recent versions of popular JavaScript libraries take advantage of the selector APIs, so you should make sure you use an up-to-date version of your preferred library.
    ??? It will also help if you add id="" attributes to elements you’ll be accessing often, because document.getElementById(myid) is the easiest and fastest way to find a node.

  • DOM Manipulation
    ?? In addition to accessing the DOM elements, you often need to change them, remove some of them, or add new ones. Updating the DOM can cause the browser to repaint the screen and also often reflow (recalculate elements’ geometry), which can be expensive.
    ?? Again, the general rule of thumb is to have fewer DOM updates, which means batching changes and performing them outside of the “live” document tree. When you need to create a relatively big subtree, you should do so without adding to the live document until the end. For this purpose you can use a document fragment to contain all your nodes.
    ? Here’s how not to append nodes:
    // antipattern
    // appending nodes as they are created
    var p, t;
    p = document.createElement('p');
    t = document.createTextNode('first paragraph');
    p.appendChild(t);
    document.body.appendChild(p);
    
    p = document.createElement('p');
    t = document.createTextNode('second paragraph');
    p.appendChild(t);
    document.body.appendChild(p);
    
    ? ? A better version will be to create a document fragment, update it “offline,” and add it to the live DOM when it’s ready. When you add a document fragment to the DOM tree, the content of the fragment gets added, not the fragment itself. And this is really convenient. So the document fragment is a good way to wrap a number of nodes even when you’re not containing them in a suitable