I am trying to pass a callback function inside a self-invoking function in JavaScript but I get 'undefined' when done function is executed.
I read this answer to write this code below:
function done() {
console.log(dateFilter.getI());
console.log(dateFilter.getF());
}
var dateFilter = (function(callback) {
var _dInicio = new Date(), _d = new Date(),
_dFim = new Date(_d.setMonth(new Date().getMonth() - 1));
return {
getI: function() { return _dInicio; },
getF: function() { return _dFim; },
setI: function(d) { _dInicio = d; },
setF: function(d) { _dFim = d; }
}, callback();
})(done);
Maybe I am using the comma operator wrong, but I think this should work. Someone could point me where i am misunderstanding something?
3 Answers 3
You're calling the done function after a return, further, you're not passing the param dateFilter.
return { -> return before calling callback `function`.
getI: function() { return _dInicio; },
getF: function() { return _dFim; },
setI: function(d) { _dInicio = d; },
setF: function(d) { _dFim = d; }
}, callback( );
^
|_ Calling callback without param `dateFilter`
Look at this code snippet
function done(dateFilter) {
console.log(dateFilter.getI());
console.log(dateFilter.getF());
}
(function(callback) {
var _dInicio = new Date(),
_d = new Date(),
_dFim = new Date(_d.setMonth(new Date().getMonth() - 1));
callback({
getI: function() {
return _dInicio;
},
getF: function() {
return _dFim;
},
setI: function(d) {
_dInicio = d;
},
setF: function(d) {
_dFim = d;
}
});
})(done);
See? now is printing the values.
5 Comments
done function scope, can I?dateFilter (getI, setI, etc.)var dateFilter = undefined, as the IIFE doesn't return anything.done function.Two reasons this cannot work:
- You are returning the result of
callbackwith your comma operator, butdonedoes not return anything - You are trying to use
dateFilterduring the IIFE initialisation ofdateFilter- it is not yet assigned the return value
There is absolutely no reason to use a callback with an IIFE. Just write
var dateFilter = (function() {
var _dInicio = new Date(), _d = new Date(),
_dFim = new Date(_d.setMonth(new Date().getMonth() - 1));
return {
getI: function() { return _dInicio; },
getF: function() { return _dFim; },
setI: function(d) { _dInicio = d; },
setF: function(d) { _dFim = d; }
};
}());
console.log(dateFilter.getI());
console.log(dateFilter.getF());
3 Comments
dateFilter has been executed, that's why I tryied using callback. Should I use promies instead?IIFE will ensure that it has been run.You're really close. Your hunch about the comma operator is correct. And I think there's a better way to wire up your done() callback so that the code is a bit more robust, and the order in which things happen is a bit clearer.
First, let's look at the return statement. All return statements do two things (evaluate the return value, then return it), but because of the comma, this one is doing three, in the following order:
- Evaluating the object literal
{ getI:... } - evaluating
callback(), which means callingcallback() - returning the return value of
callback(), since the comma operator returns it's second operand.
So, note that callback() actually gets called before your function returns, so it happens before dateFilter has a value. (And, even if it did have a value, it would be the return value from callback(), which is undefined.)
And I think there's another aspect of your code here that I think is worth a look. Callbacks typically take parameters. The simplest way to think of it is: Instead of returning a value, you pass it to the callback.
In general, code is easier to read and debug if you pass parameters instead of side-effecting shared variables.
I just made one change to your code, and it's working:
function done(dateFilter) {
console.log(dateFilter.getI());
console.log(dateFilter.getF());
}
(function(callback) {
var _dInicio = new Date(), _d = new Date(),
_dFim = new Date(_d.setMonth(new Date().getMonth() - 1));
callback({
getI: function() { return _dInicio; },
getF: function() { return _dFim; },
setI: function(d) { _dInicio = d; },
setF: function(d) { _dFim = d; }
});
})(done);
So, what did I do?
- Instead of side-effecting the
dateFiltervalue, I pass it directly tocallback.
This means: no comma operator in the return statement, and no need to side-effect the dateFilter global value. (dateFilter is now a parameter to done isntead.)
I hope that clarifies things for you. Cheers!
1 Comment
Explore related questions
See similar questions with these tags.
donedoesn't return anything. Are you at least getting the logs for the dateFilter?