Forum Moderators: open

Message Too Old, No Replies

Cutting back on highly redundant JS code

If this checked, and this checked, and this checked, and this checked...

         

Jeremy_H

3:26 am on Mar 18, 2006 (gmt 0)

10+ Year Member



I'm trying to cut back on the amount of JavaScript code I have to speed up load times.

I have a lot of statements like this:

if(!(document.q.q202[0].checked¦¦document.q.q202[1].checked¦¦document.q.q202[2].checked¦¦document.q.q202[3].checked¦¦document.q.q202[4].checked)){...}

And I was thinking I could cut it back to something like this:

if(!document.q.q202[0¦¦1¦¦2¦¦3¦¦4].checked){...}

But it doesnt seem to work. Does anybody know of any other ways I could but back my highly redundant statements?

Thanks

bedlam

5:56 am on Mar 18, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



There's not exactly less going on here, but code is much nicer--I'm not really sure how you could reduce it if you really do need to test a whole array's worth of items:

for (var i=0;i<document.q.q202.length; i++) {
if (!document.q.q202[i].checked) { ... }
}

-b

Jeremy_H

7:05 am on Mar 18, 2006 (gmt 0)

10+ Year Member



Thanks bedlam,

I've always been a bit wary of the i variable, since I never really understood it, but it does look like that's the way I need to move.

I'm just wondering though, does anybody know if its more CPU demanding?

Thanks

bedlam

7:36 am on Mar 18, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I dunno if it's more demanding or not (it'd depend partly on how many items are in the array), but since you sound a bit unsure about how it works, here's the code again with comments:


/*
Start a for loop [developer.mozilla.org]. This is the overall structure you see:

for ( ... ) { ... }

Notice it has two parts:

  1. The first part (between the parentheses) has three parts:

    a) An initial value for the counter [ var i=0; ]. We use this to start counting at zero, since the first index of an array is zero.

    Note that 'i' is commonly used as a counting variable, but not for any particular reason. Feel free to use 'fubar' or anything else instead...

    b) A condition or test [ i<document.q.q202.length ]. This is the condition that determines whether the loop will execute--in this case, if 'i' is less than the length [developer.mozilla.org]
    of the given array, the loop will execute again...

    c) An increment [developer.mozilla.org] [ i++ ]. We use this to increase the value of the variable 'i'--this makes sure that the loop will stop at some point, because if we keep adding one to i, eventually the value of i will be greater than the number of indices in the array...

  2. The second part {between the braces} is the statement part. Here, you put one or more statments that will be executed every time the loop loops.

    In this particular case, every loop of will check to see if document.q.q202[i] is not checked, and do something--or not--depending on whether the expression (!document.q.q202[1].checked) evaluates as true or false.


*/
for (var i=0;i<document.q.q202.length; i++) {
if (!document.q.q202[i].checked) { ... }
}

-b

Bernard Marx

9:32 pm on Mar 18, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



does anybody know if its more CPU demanding?

I guess it should take about twice as much CPU time as the original. Before I suggest why (and a solution) I'll say that it probably doesn't really matter so much in this type of context. The user clicks "Submit"; something happens. They won't notice if it takes 20 ms or 80. That is unless your are repeating this kind of coding over a gargantuan form and / or you have demanding Flash animations being CPU gluttons on the page.


for (var i=0;i<document.q.q202.length; i++) {
____if (!document.q.q202[i].checked) { ... }
}

Here's some of the things happening on every iteration:

Referencing the document.q.q202 collection:

  1. Attempt to find "document" in local function namespace.
  2. Flip out to global namespace, and find it there. In browsers especially, global variables are apparently quite inefficient to dereference.
  3. Find "q" in document object's namespace.
  4. Find "q202" in q's namespace

This is all costly. Referencing properties of DOM objects is probably the more time consuming part of the scripting, far more than "pure" Javascript things like comparing two values, or incrementing a variable.

..and in the loop,

document.q.q202
is referenced twice. This is why I reckon it will take about twice as long.

The DOM object properties:

length
and
checked
are also referenced on each iteration.


The usual approach is to cache as much (and as far down each reference chain) as possible in local variables before entering a loop. In many cases, this can also make the code shorter, and easier to manage too.

In this case, we cache document.q.q202 and it's length.

[pre]
var q202 = document.q.q202;
for (var i=0,L=q202.length; i<L; i++) {
if (!q202[i].checked) { ... }
} [/pre]

There are minor refinements to be made from here, such as going through the collection backwards so that i can be compared against zero, and L is redundant, a while loop is said to be faster too. but the gain is not so important compared the the improvements made above.

[pre]
var q202 = document.q.q202, i = q202.length;

while (i>0;) {
if (!q202[--i].checked) { ... }
} [/pre]

Bernard Marx

10:38 pm on Mar 18, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



<ERROR>

while (i>0;) {

Remove the rogue semi-colon.