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