How could I improve the performance of my below JQuery code:
var firstRowCellsWidth = new Array();
function initialize();
$('table.rgMasterTable > tbody > tr:first > td').each(function () {
firstRowCellsWidth.push({
normalCellWidth: $(this).width(),
firstTemplateCellWidth: $(this).find('table > tbody > tr > td:first').width()
});
});
}
I'm using :first
, $(this)
, .find(, >
, and each()
. these apparently degrade the performance?
What should they be replaced with? or what are the开发者_StackOverflow中文版ir equivalent native javascript code?
I'd guess using for loop instead of the each()
method. what about the rest?
Purpose of the code: To figure out the width of each column of the table. the master table has also a nested table as can be seen.
Thanks,
var firstRowCellsWidth = [];
function initialize(){
var tables = document.getElementsByTagName("table");
for(var i=0; i<tables.length; i++){
if(/(^|\s)rgMasterTable(\s|$)/.test(tables[i].className)){
//a className is only valid if the className is contained within a space/nothing(^) and a space/nothing($)
var tcell = tables[i].rows[0].cells; //Any cell
for(var j=0; j<tcell.length; j++){
firstRowCellsWidth.push({
normalCellWidth:tcell[j].offsetWidth,
firstTemplateCellWidth:tcell[j].getElementsByTagName("td")[0].offsetWidth
//the first cell of any row of any table = the first occurence of a TD element
});
}
//break;
//Uncomment the previous line if you want to enumerate through all tables whose class equals .rgMasterTable
}
}
}
As efficient as possible, without use of JQuery (frameworks are used too often by lazy scripters who do not mind a loss in computing efficiency).
Note that an error will be thrown when the document structure does not match your description (tcell[j].getElementsByTagName("td"[0] is undefined
).
EDIT: JavaScript vs JQUery in terms of speed
As a response to maxedison (third comment), who questioned my statement that JQuery is less efficient than JavaScript. Copy the code snippets belows and paste them in the location bar (of this page). A prompt will appear, where the number of tests can be specified. After the test has run, an alert pops up, showing the needed amount of milliseconds to perform these tests. Two test cases are provided:
Native JavaScript test case:
javascript:alert((function(m){
for(var i=0, t=new Date; i<m; i++){
document.getElementsByTagName("table")[0].rows[0].cells[0];
}
return (new Date).getTime()-t.getTime();
})(prompt("Native\x20JS,\x20repeat\x20n\x20times:","10000")));
JQuery test case. Warning: Do not start with a large number of tests:
javascript:alert((function(m){
for(var i=0, t=new Date; i<m; i++){
$("table > tbody > tr > td:first");
}
return (new Date).getTime()-t.getTime();
})(prompt("JQuery,\20repeat\x20n\x20times","10")));
At my 1 year old laptop, using FireFox 3.6.22, 10000 calls using native JavaScript equals 5 JQuery executions.
Are you actually experiencing performance problems? It doesn't look like this is the kind of loop that is getting run so many times that saving a couple ms per iteration would make any noticeable difference.
Anyway, I realize you may be asking out of curiosity, so here is one way that performance could be improved:
- before pushing the values, store
$(this)
in a variable. Remember that$
is actually a function, so$(this)
means that you are calling the function$
and passing the argument this to it. As a general rule of thumb, if your'e going to need to use$(this)
more than once, storing it in a variable will be faster since it avoids making additional$
function calls.
I'd also be curious to know whether a standard for
loop would ever be significantly faster than .each()
. However, when you ask "what are their equivalent native javascript code?", be aware that the entire reason you're using jQuery is because it's a lot easier to write & read, and that most "native javascript" equivalents are going to look & be far more complicated. So that question itself kind of defeats the purpose of using jQuery in the first place, unless of course you really are experiencing some performance issues.
One improvement would be to store a reference to any jQuery object you intent to use more than once..
So instead of using multiple times $(this)
use
var $this = $(this);
and use $this
from now on to refer to that object..
function initialize(){
$('table.rgMasterTable > tbody > tr:first > td').each(function () {
var $this = $(this);
firstRowCellsWidth.push({
normalCellWidth: $this.width(),
firstTemplateCellWidth: $this.find('table > tbody > tr > td:first').width()
});
});
}
Replacing the .each with a native loop likely won't do anything, the .each is just doing a for loop anyway.
Are you actually having problems with speed?
Assuming that you're going to have static layouts for your tables you could figure out how to navigate down using .childNodes[]
. You would do something like
document.getElementById('myTable').childNodes[0].childNodes[0].childNodes[0]
. As you can imagine, that gets pretty ugly pretty fast.
You could probably speed up your selectors a little bit by getting rid of the > trbody >
part, unless you have a table in your trbody
and another in a trhead
it's not doing anything.
精彩评论