3

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!!

1 Answer 1

5

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.

6
  • 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, 2014 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, 2014 at 19:36
  • What's undefined in the callback example?
    – ari gold
    Apr 17, 2014 at 20:18
  • 1
    @arigold The return value of bar(), which will be passed into foo() as its second argument.
    – Katana314
    Apr 17, 2014 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, 2014 at 20:21

Your Answer

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

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