How the JQuery each () function optimizes the performance of the cyclic DOM structure _jquery

Source: Internet
Author: User
It's really easy to use a problem if you just stay on the level of jquery and don't know what it is. That is why I have not been advocating jquery in recent times, and this framework's API setting has misled people into misleading.
Copy Code code as follows:

$.fn.beautifytable = function (options) {
Define default configuration items, and then overwrite with options
Return This.each (function () {
var table = $ (this),
tbody = Table.children (' tbody '),
TR = Tbody.children (' tr '),
th = tbody.children (' th '),
td = Tbody.children (' TD ');
Class for individual content
Table.addclass (Option.tableclass);
Th.addclass (Options.headerclass); 1
Td.addclass (Options.cellclass); 2
Class of odd and even rows
Tbody.children (' Tr:even '). addclass (Options.evenrowclass); 3
Tbody.children (' tr:odd '). addclass (Options.oddrowclass); 4
Alignment method
Tr.children (' Th,td '). CSS (' text-align ', options.align); 5
Add Mouse suspension
Tr.bind (' mouseover ', addactiveclass); 6
Tr.bind (' mouseout ', removeactiveclass); 7
Click Color
Tr.bind (' click ', Toggleclickclass); 8
});
};

Overall, the code is good, clear, logical, and what you want to do is clearly explained by the comments. But as the author says, when there are 120 rows in the table, ie already reflects that the script is running too long. Obviously, this function is inefficient, or even extremely low, from the performance point of view.

So, starting from the code level analysis, this is a standard jquery plug-in function, there is a typical return This.each (function () {...};), the form of code, if the author writes this code, not by the script without thinking, You should be aware of what a function of jquery has done.

In short, the Jquery.fn function, most of which is a single invocation of each, is naturally a traversal of the selected elements and a specified operation on an element. So take a look at the code above and how many traversal you've made, assuming you've chosen only 120 rows, each row has 6 columns, plus a 1-line header:
Iterate through th, add headerclass, and the number of elements is 6.
Traverse TD, add Cellclass, element number is 6*120=720.
To find odd numbers from all TR, you need to iterate through all of the TR, with an element of 120.
Iterate through the odd TR, add Evenrowclass, and the number of elements is 120/2=60.
To find even in all TR, one traversal of all TR is required, with an element number of 120.
Traverse even-numbered TR, add Oddrowclass, and the number of elements is 120/2=60.
Iterate through all th and TD, add Text-align, element number is 120*6+6=726.
Iterate through all TR, adding the MouseOver event with an element of 120.
Iterate through all TR, adding the Mouseout event with an element of 120.
Iterate through all TR, adding the Click event with an element of 120.
For convenience, we simply assume that accessing an element in the traversal takes 10ms, so how much time does this function take? This function has encountered 2,172 elements, time consuming 21720ms, that is, 21 seconds, it is obvious that IE should be reported for too long script execution.

Know the reasons for inefficiency, to fundamentally solve, naturally have to find ways to merge the cycle, at first glance, according to the above code in the comments in the number, at least the following points can be merged:
3 and 4 can be merged into one cycle, from 120+60+120+60 to 120, and 240 less. 1, 2, and 5 can be merged into one cycle, from 6+720+726 to 726, and 726 reduced. 6, 7, 8 can be merged into one cycle, from 120+120+120 to 120, reduced by 240. Further, 3, 4 and 6, 7, 8 can be merged into one cycle and continue to reduce by 120. Add up, we have reduced the 240+726+240+120=1326 element operation altogether, total 13260ms. After optimization, our function time becomes 21720-13260=8460ms, or 8s.
There may be a doubt here, from the structure of the table, all the th and TD elements must be within TR, so why not put the 1, 2, 5 loops in the loop of the TR, forming a nested loop, not faster?
There are 2 main reasons why this is not done here:
First, no matter where the 1, 2, 5 are placed, one access to all th and TD elements will not be reduced.
On the other hand, $ (' th,td ') this selector, in sizzle, will be translated into 2 getelementsbytagname functions of the call, the first time to get all th, the second acquisition of all TD, and then to merge the collection. Since getElementsByTagName is a built-in function, it can be thought that the function is not cyclic, that is, the complexity is O (1), the same set of aggregation using an array of related functions, is the operation of memory, the complexity of the same is O (1).

Conversely, if you use the $ (' th, ' TD ') selector in the loop of the TR element, you invoke the 2 getElementsByTagName on the TR element, because the function executes the same time regardless of which element is invoked, so it is used in cyclic tr. Instead of a 119*2 function call, the efficiency does not rise and fall.
As you can see, the basic knowledge of the sizzle selector is also an important aspect of helping to optimize the jquery code.
Don't let JavaScript do everything.

Based on the previous basic optimizations, the time has been reduced from 21 seconds to 8 seconds, but the 8-second number is clearly unacceptable.
Further analysis of our code, in fact, loop traversal is the language level of content, its speed should be quite fast. And for each element of the operation, is jquery provided by the function, compared to the traversal, is to occupy most of the resources of the master. If the access element in the traversal is 10ms, you are welcome to perform a addclass at least 100ms-level consumption.

Therefore, in order to optimize the efficiency further, we have to start with reducing the operation of the elements. Again, carefully back to the code and found that the function has a lot of changes to the style, including at least:
Add class to all th.
Add class to all TD.
Add class to the TR-odd-even line.
Add a text-align style to all th and TD.
In fact, we know that CSS itself has a descendant selector, and the browser native to the parsing of CSS, more efficient than let JavaScript to the element one by one plus class.

So, if the CSS is controllable, then this function should not have Headerclass, cellclass these two configuration items, but as far as possible in the CSS configuration:
Copy Code code as follows:

. beautiful-table th {/* headerclass content */}
. beautiful-table TD {/* CELLCLASS content */}

Furthermore, for TR's odd and even line style, it can be implemented using the Nth-child pseudo class in a partial browser, which can be probed by feature and only use AddClass to add styles in browsers that do not support the pseudo class. Of course if you just want to optimize the IE series, this one can be ignored.

For: Nth-child pseudo class detection, you can use the following ideas: Create a stylesheet, and then create a rule, such as #test span:nth-child (odd) {display:block;}. Create the corresponding HTML structure, a div with the test ID, and place 3 spans inside.

Add the stylesheet and Div together in the DOM tree. View the runtime display style for the 1th and 3rd spans and, if block, the pseudo class is supported. Delete the created stylesheet and Div, and don't forget the results of the cache probes. Finally, for all th and TD elements to add text-align style, can also be optimized through CSS. Since you don't know which align to add, write a few more styles:
Copy Code code as follows:

/* CSS Style * *
. beautiful-table-center Th,.beautiful-table-center td {Text-align:center!important;}
. beautiful-table-rightright Th,.beautiful-table-rightright td {Text-align:rightright!important;}
. beautiful-table-left Th,.beautiful-table-left td {Text-align:left!important;}
/* JavaScript * *
Table.addclass (' beautiful-table-' + options.align);

Of course, the above mentioned optimization, is based on the control of the CSS situation, if you can not contact the CSS style, such as this is a general-purpose plug-in function, will be completely uncontrollable third-party use, then how to do? Nor is there a complete solution:
Look for all the CSS rules on the page, such as Document.stylesheets. Iterate through all the rules and take out the Headerclass, Cellclass, etc. in the configuration item. Extract all the styles from the required classes and assemble them into a new selector, such as beautiful-table th. Use the created selector to generate a new stylesheet and add it to the DOM tree. So just add beautiful-table to table and this class is done.

Of course, the above practice is also quite time-consuming, after all, to traverse stylesheet, and create stylesheet. Specific is not to improve the efficiency of a lot of help, then the size of the page will have different effects, whether the use of the function to see the specific needs of designers, here is to mention a strategy.

In general, by doing as little as possible JavaScript, more styling tasks to the CSS, the browser's rendering engine to complete, but also to further optimize the function, assuming that the addclass, CSS calls need 100ms, this optimization directly eliminates the original 120 + 726=846 operation, saving 84600ms of time (of course there are exaggerated components, but for the entire function of consumption, this is really a big piece).

This article, just to optimize the various implementations of jquery, involves only the analysis of the entire process of jquery, details and optimization direction, and does not mention some basic basic optimization methods, such as: first to remove the entire table from the DOM tree, Do all the work and put it back in the DOM, reducing repaint. Change MouseOver and Mouseout to MouseEnter and mouseleave, reducing the execution of duplicate event functions that result from the next correct event bubbling model. For th, TD and other simple elements of choice, give priority to the use of native getElementsByTagName, the elimination of sizzle analysis selector time.

Finally, this article is just to illustrate that for front-end developers, although the browser may be a black box, but a lot of frameworks, tools, libraries are open, in the use of a certain degree of understanding before, it will contribute to personal technical upgrading and final product quality optimization, "know it but do not know why" is a very taboo situation.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.