I was writing an event handler function and realized that I was coding loops in a way that is not usually possible in other languages. Lets discuss this technique, which can help improve the run-time of certain iterative
for
loops.
Suppose you have an event callback function with multiple triggers and a collection of something that you need to iterate through each time the callback function is made (like rows in a table or list items in a list). You then need to do something different to the collection depending on what trigger hit the callback function. In most languages you would have a for loop containing a switch statement with N cases (or if statements if you absolutely cannot use a switch). Here is an example that executes a function on each list item depending on the trigger id:
function callback(e) { var items = document.body.getElementsByTagName(li); var trigger = Event.getTarget(e); // this is a Framework function that is really useful var id = trigger.id; for (var i=0, j=items.length; iid1 : someFunctionForId1(items[i]); break; caseid2: someFunctionForId2(items[i]); break; caseid3: someFunctionForId3(items[i]); break; caseid4: someFunctionForId4(items[i]); break; default: // any other id someFunctionForId5(items[i]); break; } } }
This is perfectly valid code and will work great on small sets, because the switch statement has a very small run-time cost (switches are very quick seek structures in JavaScript), and on a small set, you will not execute the statement many times. The runtime as an equation would be:
k1 * n = r where k1 = the constant cost of the switch n = the number of values in the array and r = run-time
There is a better way to write this function, where the select statement is only executed once:
function callback(e) { var items = document.body.getElementsByTagName(li); var trigger = Event.getTarget(e); // this is a Framework function that is really useful var id = trigger.id; var fx = null; switch (id) { caseid1: fx = someFunctionForId1; break; caseid2: fx = someFunctionForId2; break; caseid3: fx = someFunctionForId3; break; caseid4: fx = someFunctionForId4; break; default: // any other id fx = someFunctionForId5; break; } for (var i=0, j=items.length; iFor this callback the runtime is:
(k2 + k1) + (c * n) = r where k1 = the constant cost of the switch k2 = the constant cost of assigning the function to variable fx c = the cost of seeking and executing the function fx n = the number of values in the array and r = run-timeI have not done the actually runtime analysis, so I do not have the exact numbers, but you should not have to stretch your imagination far to assume that the cost of c < k1, so as long as the number of iterations (n) are overwhelm the constant (k1 + k2), then the latter algorithm is faster. The exact equation for this comparison is:
(k1 + k2) + (c * n) = k1 * n where k1 = the constant cost of the switch where k2 = the constant cost of assigning the function to variable fx c = the cost of seeking and executing the function fx n = the number of values in the arraycomputing for n, you get:
n = (k1 + k2) / (k1 - c)If you have time, try profiling some loop code to figure the exact numbers. My assumption is that n is between 10 & 20, so anytime I iterate on a list greater than 10 and can use this pattern, I do.