2

I read an online book. It gave an callback pattern example as follow.

var findNodes = function () {
    var i = 100000, // big, heavy loop
        nodes = [], // stores the result
        found; // the next node found
    while (i) {
        i -= 1;
        // complex logic here...
        nodes.push(found);
    }
    return nodes;
};
var hide = function (nodes) {
    var i = 0, max = nodes.length;
    for (; i < max; i += 1) {
        nodes[i].style.display = "none";
    }
};

// executing the functions
hide(findNodes());

It said that this is not efficient, for it loop through found nodes twice, and the following code is more efficient.

// refactored findNodes() to accept a callback
var findNodes = function (callback) {
    var i = 100000,
        nodes = [],
        found;

    // check if callback is callable
    if (typeof callback !== "function") {
        callback = false;
    }

    while (i) {
        i -= 1;

        // complex logic here...

        // now callback:
        if (callback) {
            callback(found);
        }

        nodes.push(found);
    }
    return nodes;
};
// a callback function
var hide = function (node) {
    node.style.display = "none";
};

// find the nodes and hide them as you go
findNodes(hide);

However, both of them are O(n), and the overhead of calling a function may be large, which causes each iteration in findNodes() (with callback) takes more time. So I wonder if this modification really makes different as the author said. And how should I measure the cost of the two implements?

2
  • This will be dependent in some part on how many nodes on average findNodes is going to return. If it is quite small then either approach will have pretty much the same performance. For very large it may be that the callback is better. However, as the "complex logic" is handled out by findNodes (in the first example) then the further iteration shouldn't be too costly. Commented Jun 27, 2012 at 8:52
  • 1
    jsperf.com/normal-vs-callback Commented Jun 27, 2012 at 9:02

2 Answers 2

3

Depending on the size of the array, the example where it's only looped once can be more efficient.

However, your concerns are correct. Especially in bit older JS engines there is significant overhead in function calls.

Like with all performance optimizations, this is something you should measure. Use a profiler to test the code to find bottlenecks, then optimize, then rerun profiling to find out if it had a positive effect.

Sign up to request clarification or add additional context in comments.

Comments

2

I put the two examples in two functions in an HTML file, and used the Chrome console to time them, like this:

console.time('slow'); slow(); console.timeEnd('slow');
console.time('fast'); fast(); console.timeEnd('fast');

This shows that the first example, the "inefficient" one, runs twice as fast as the second implementation.

2 Comments

jsperf.com/normal-vs-callback but maybe there might be some usecases where it's the other way around.
I'm almost tempted to vote this answer down! You have posted the least relevant part of the code, ie How you timed the calls. You don't mention a) How you implemented the complex logic of findNodes b) How many nodes were selected by findNodes c) What type of markup elements you used...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.