Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm pretty sure that the following two snippets are equivalent but I wanted to double check:

CALLBACK STYLE

function foo(input, callback) {
    // do stuff with input

    callback();
}

function bar(input, callback) {
    // do stuff with input

    callback();
}

foo("hi", bar("bye", function() {
                       // do something cool
                     }));

Note that the callbacks take no arguments.

PLAIN STYLE

function foo(input) {
    // do stuff with input
}

function bar(input) {
    // do stuff with input
}

foo("hi");
bar("bye");
(function() {
    // do something cool
})();

Of course if they are equivalent it would make sense to me to use PLAIN STYLE as it's simpler and cleaner.

I realize the scope of the anonymous function (who does something cool) is different in the two cases.. I'm not concerned with that aspect of "equivalence".

UPDATE

I'm working on some legacy code and find quite a bit of it confusing. This is the original code that prompted this question. Specifically the noted 6 or so lines of code.

var CoolNamespace = (function () {
    var container_element,
        keysLength = 0;

    //
    // THE FOLLOWING 6 OR SO LINES IS WHAT I'M CURIOUS ABOUT
    //
    _createCoolObject(function (coolObject) {
        _appendFrameToContainer(coolObject, function () {

            // Post form
            _sendForm(function (form) {
                container_element.appendChild(form);
                form.submit();
            });
        }); 
    });

    function _sendForm (callback) {
        // Sends client data via post.
        if (keysLength != 0) {
            var form = _createForm();
        } else {
            throw new Error("error message stub");
        }
        callback(form);
    }

    function _appendFrameToContainer (frame, callback) {
        if (typeof container_element != "undefined") {
            container_element.appendChild(frame);
        } else {
            throw new Error("error message stub");
        }
        callback();
    }

    function _createCoolObject (callback) {
        var coolObject = { level: "very cool" };

        callback(coolObject);
    }

    function _handleMessage (event) {
        // it's not really about this function
    }

    function _createForm() {
        // it's not really about this function either
        var form;
        return form;
    }
})();

When stepping through the code, it seemed to be the case that the body of _createCoolObject was invoked before the argument (which is a function). I think my confusion was that a the argument to _createCoolObject is a function literal which evaluates to a function but that function is not itself evaluated until the line callback(coolObject). Thanks for the clarification!!

share|improve this question
add comment

1 Answer

up vote 4 down vote accepted

They are not equivalent in their execution order.

foo("hi", bar("bye", function() {
    // do something cool
}));

This must first evaluate bar("bye", function() { … }), then calls foo("hi", …) with the result of that invocation. As the return value of bar is undefined, you'll get an error when you call that as a function.

If you want the callback example to be equivalent to your plain example, you'd have to do:

foo("hi", function() {
    return bar("bye", function () {
        // do something cool
    });
});

I would also change the definition of foo and bar so that they do return callback(), which allows for more general code.

Notice that this callback style is similar – but not equivalent – to continuation passing style.

share|improve this answer
    
So maybe I had the order wrong - For the PLAIN EXAMPLE would it have been equivalent if I had written: (function() { \\ do something cool })(); followed by bar("bye"); followed by foo("hi");? (that is, if I inverted the order of the function calls) –  ari gold Apr 17 at 19:34
    
@arigold No. For starters, your callback example produces an error because you want to call undefined as a function. So the equivalent plain code would be bar("bye"); (function(){ … })(); undefined(); –  amon Apr 17 at 19:36
    
What's undefined in the callback example? –  ari gold Apr 17 at 20:18
1  
@arigold The return value of bar(), which will be passed into foo() as its second argument. –  Katana314 Apr 17 at 20:20
    
@arigold undefined is a special value in JavaScript. It's the value unassigned variables have, and the return value of functions without an explicit return. It is similar to null in its semantics. Read more in the Mozilla docs –  amon Apr 17 at 20:21
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.