I'm brushing up on callback functions and came across the following passage from http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/#
"When we pass a callback function as an argument to another function, we are only passing the function definition. We are not executing the function in the parameter. In other words, we aren’t passing the function with the trailing pair of executing parenthesis () like we do when we are executing a function.
And since the containing function has the callback function in its parameter as a function definition, it can execute the callback anytime."
Can someone explain that? Here are two examples they provided.
//The item is a callback function
$("#btn_1").click(function() {
alert("Btn 1 Clicked");
});
Here is another example:
var friends = ["Mike", "Stacy", "Andy", "Rick"];
friends.forEach(function (eachName, index){
console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick
});
"Note that the callback function is not executed immediately. It is “called back” (hence the name) at some specified point inside the containing function’s body. So, even though the first jQuery example looked like this:
//The anonymous function is not being executed there in the parameter.
//The item is a callback function
$("#btn_1").click(function() {
alert("Btn 1 Clicked");
});
the anonymous function will be called later inside the function body. Even without a name, it can still be accessed later via the arguments object by the containing function."
For the first example with jquery, what are they saying exactly. If the #btn_1 element is clicked, will the anonymous function be executed? I am assuming it will be executed if the button is clicked, but the wording from the passage was confusing?
Similarly, for the second example, do they not need to call the function that they passed as an argument bc its anonymous?
In both examples, you are passing an anonymous function as a parameter.
$("#btn_1").click(function() {
alert("Btn 1 Clicked");
});
jQuery's click method takes a function as its first parameter. So imagine that click's function definition is this:
function click(fn) {
// fn will contain a reference to any
// function passed as the first parameter to click
// merely calling fn does nothing, because you are just 'calling'
// the reference.
fn;
// Since what is inside of fn is a function, you can execute it
// with the () syntax
fn();
}
// Now, you have many ways to pass a function as the first parameter to the function
// 1. As an anonymous function:
click(function() {
console.log("Hi");
});
// 2. As a named function:
click(function hello() {
console.log("Hi");
});
// 3. As a reference to a function declaration
function hiThere() {
console.log("Hi");
}
click(hiThere);
// 4. As a variable that holds an anonymous function inside
var howdy = function () {
console.log("howdy");
};
click(howdy);
Just imagine that functions are like variables, but they have content inside that can be executed with () at the end.
function hi() {
console.log('bye');
}
hi; // Calls the reference, but does not execute it. This does nothing.
hi.toString(); // Returns the function as a string
hi(); // Executes the code within the function
Whenever you declare a named function, you can do stuff with it according to its name, like you would do with variables. Of course, unlike variables, they hold executable code inside, and not values.
You can't reference an anonymous function, because it's well... anonymous. UNLESS, you hold it inside of something that has a name, like a var.
var iHoldAFunctionInside = function () {
console.log('Im not so anonymous now');
};
iHoldAFunctionInside(); // Logs "Im not so anonymous now"
And that is why you can pass an anonymous function as a parameter to a function, and it can execute it as a callback. Because the parameter now 'holds' the anonymous function inside of it:
function iExecuteYourCallback(callback) {
// callback contains the anonymous function passed to it
// Similar to doing:
// var callback = function () { };
callback();
}
iExecuteYourCallback(function() {
console.log('Im a callback function!');
});
Hope this helps clear things a bit.
In javascript functions are first class members to you can pass a function as an parameter and the called function can accept it as a named argument.
A simple example can be as below
function testme(callback) {
//here the argument callback refers to the passed function
//the timer is used just to delay the execution of the callback
setTimeout(function () {
//the passed function is called here
callback();
}, 1000)
}
testme(function () {
alert('x')
})
Demo: Fiddle
In your examples, yes the first callback will be executed once the element with id btn_1 is clicked.
Related
I know i can have a function as a parameter in javascript. I can also run that function that was given as a parameter. Here's an example:
function myfunction(param1, callbackfunction)
{
//do processing here
callbackfunction();
}
What if i wanna give an anonymous function, how will this run inside the outer function.
For example with a function like
setTimeout(function(){
})
How is this anonymous function directly run without a name?
You don't need a name to call a function. Names are only useful for use in a debugging tool (e.g. when examining a stack trace).
To call a function you need an expression that resolves as the function, which you can follow with ().
You're passing the function as the first argument to setTimeout, so it gets stored in the first parameter of that function. setTimeout's internals then call it.
You do the same with your code, only it is the second argument.
myfunction("some param", function () { /* ... */ }) ;
Maybe this makes it clearer?
function callFunction(param1, callbackfunction) {
console.log('callFunction', param1)
//do processing here
callbackfunction(param1);
}
function myCustomCallback(param) {
console.log('myCustomCallback', param)
}
setTimeout(callFunction.bind(this, 'one', myCustomCallback ), 1000)
setTimeout(callFunction.bind(this, 'two', function(p) {alert(p)} ), 2000)
I have the following jQuery code:
function next() {
//some code here
}
function previous() {
//some code here
}
$("#next").click(function(){
next();
});
$("#previous").click(function(){
previous();
});
This works, but this doesn't:
$("#next").click(next());
$("#previous").click(previous());
Why is this happening? Is there a problem in my code, or is this just a thing with jQuery? Note: #next and #previous refer to two buttons in my html file.
The callback should be a reference to the function.
Why $("#next").click(next()); doesn't work?
func() is a function call and not a reference, which is why it is called immediately.
This,
$("#next").click(function(){
next();
});
is a preferable way in case you need to pass arguments.
Else,
$("#next").click(next) //notice just the signature without ()
This works (if the functions next and previous are defined):
$("#next").click(next);
$("#previous").click(previous);
In this case the next and previous are also callback functions, the difference between the two is,
when you call this line
$("#next").click(next()); the function is executed immediately, and you are passing the result of the next function to the eventHandler of jQuery.
and in this case
$("#next").click(next); you are passing the function next to the EventHandler of jQuery.
Btw.: in the jQuery API Documentation (https://api.jquery.com/click/) it shows all parameters for the click function and the required types it states: "...handler Type: Function( Event eventObject ) A function to execute each time the event is triggered. ..."
try like this you will get your answer,
function next() {
//some code here
}
function previous() {
//some code here
}
$("#next").click(next);
$("#previous").click(previous);
working demo jsfiddle Example
What is going on there is a little bit obscured by the syntax of anonymous functions function() { ... }. What you are doing by that is passing a function, without calling it. And I want to explain how this works:
If you have a simple function
function next() { return 5 };
It will simply return the value 5, if you call it from somewhere:
a = next(); // value of a will be 5
But what you can do too, is to pass the whole function to a. This is possible, because functions in JavaScript are actually objects:
a = next;
b = a(); // value of b will be 5
If you look at the syntax, it shows you, that putting parentheses () at the end of a function invokes it, and returns the return value. While the naked string, without parentheses hands you the function itself.
So what is a callback now, and what does click() like to get as a parameter? A callback function is a function, that gets called later; we actually hand it over, to get called later. click() would like to get such a function as parameter, and it should be clear now, that we have to pass the function without parentheses, to enable click() to call it later, instead of just passing a 5 to it.
$("#next").click(next);
So how does then the initial syntax with the anonymous function work?
function() { next(); }
actually wraps your next() into another function, which is anonymous – because it does not have a name – but is working in the same way as a named function. You can even set a variable by it:
a = function() { next(); } // a will be the anonymous function that calls next()
But calling that function a() will return nothing, because the anonymous function does not return a value (To be exactly: every function call in JavaScript is returning at least undefined, but that's a technical detail).
It can even be called immediately by putting parenthesis at the end of it:
a = function() { return next(); }() // value of a will be 5
Adding the return there will make sure, the return value of next() will be passed through the anonymous function.
This should make clear why
$("#next").click(function(){ next(); });
is working, and why
$("#next").click(next());
is not, but
$("#next").click(next);
will be a good solution.
$("#next").click(next); would work. Notice parenthesis are not required as the function/callback handler should be passed as a parameter.
I have the following Problem, I want to call a function b like I call the function a.
Here is the example:
$('#clickme').click(function () {
console.log("abc");
});
function a() {
console.log("a");
}
function b(b) {
console.log(b);
}
$('#clickmea').click(a);
// how to call this method without using a anonymous function?
$('#clickmeb').click(b("ab"));
Or is it not possible to call b("ab") without using a anonymous function?
JSBin exmaple
You can't do that without using either a anonymous function:
$('#clickmeb').click(function(){b("ab")});
Or a wrapper function:
function callback(){
b("ab")
}
$('#clickmeb').click(callback);
There's no need to return a anonymous function from the callback. That's just extra code that doesn't do anything useful.
In fact, it wouldn't carry over variables passed to the callback:
function callback(){
return function(){
b("ab") // There will be no arguments passed to this anonymous function, unless you explicitly add them.
}
}
This is a simple question. Here is my code:
$(document).ready( function () {
func1( "foo", callback);
function callback(param){
alert(param+" is my name");
}
function func1(name, cb) {
cb(name); // alerts "foo is my name"
callback("bar"); // alerts "bar is my name"
}
});
I want to know:
Which one of the function calls inside func1 is the correct callback and why?
Or are they both correct?
Isn't callback("bar"); a normal function call?
Callbacks are meant to let a caller specify what a function should do at some defined point in that function's execution. The function being called shouldn't know the name of that callback function ahead of time. So they'll often be passed to a function as an argument and the function that's supposed to call the callback should just invoke that argument.
When you call callback("bar") in func1, you're totally missing the point of callbacks. You may be invoking the function that you happen to use as a callback, but the point of callbacks is that func1 isn't supposed to know about that. It's just supposed to call the function that's been passed in as an argument (cb). When I'm calling func1 I should be able to pass a completely different callback function and func1 should just call that function without knowing what its name is (it may not even have one!).
The "correct" way is cb(name).
callback("bar"); is directly invoking the callback function where as cb(name); calls the reference passed to the func1,
cb(name); seems to be the correct way here.
First one. Function calls another one which has been pased as a parameter.
It seems like most jquery methods follow this this form for callbacks:
$(SUBJECT).method(function() {
//do stuff
}, /*callback here*/ function(){
//do stuff
});
like for instance
$(foo).click(function() {
$(bar).fadeIn(300, function(){
//call back here
});
});
fiddle
How can I get this function to pass by reference with this code?
var Class = function() {
var callback1;
var callback2;
function buildStuff(data, callback) {
element.onclick = function() {
doStuff(callback);
};
}
function doStuff(callback) {
callback();
}
return {
"setCallback1":function(fn) {
callback1 = fn;
},
"setCallback2":function(fn) {
callback2 = fn;
},
//may rebuild with different data, but same callback
"buildFoo":function(data) {
buildStuff(data, callback1);
},
//may rebuild with different data, but same callback
"buildBar":function(data) {
buildStuff(data, callback2);
}
};
}
function main() {
var object = Class();
object.setCallback1(function() {
//do stuff
});
object.setCallback2(function() {
//do something else
});
}
When you actually click on the element, callback is undefined. I would expect it to be the anonymous function I set it to with the setCallback function because the user click occurs after I call the setCallback function.
Thanks!
EDIT: Thanks for the input. I should have mentioned I need to be able to dynamically set what callback equals. So, I can't just eliminate the callback parameter from buildStuff.
EDIT2: Very sorry for the confusion; I realize my example was a bit too out of context to show what I am doing. buildStuff is actually a private member function (using the module pattern) that is called repeatedly. Depending on what is being built, it needs a different callback. The callback is actually set outside of the class (well, module pattern class), so it has to be dynamic. I've updated my code, and again, sorry for the bad example.
The click handler you create in buildStuff creates a closure over the local variables. You pass callback to your buildStuff function, but at the time you pass it, it's undefined. As this shadows the other callback variable, you always see this value of undefined, rather than the state of the other callback variable.
Instead, don't pass a parameter to buildStuff, and the closure will be created, and will capture the callback variable you want.
function buildStuff() {
element.onclick = function() {
doStuff(callback);
};
}
Imagine this;
Your global variable callback points to a value (in this case undefined).
When you buildStuff in main(), you pass the value pointed to by callback (undefined) as a parameter to buildStuff
Your click handler creates a closure over local variables + other variables in scope (note that the local callback shadows the global callback). callback in your event handler is now undefined.
You then setCallback. setCallback changes the value the global callback variable points to using the = operator. The global callback and local callback now point to different values, which is why you don't see the callback in the event handler update.
What you want to do in this situation is to change the value pointed to by callback, so other variables pointing there also update, but JavaScript doesn't let you do this.
Yes, but you've already called buildStuff before setCallback.
The contents of callback at the time (undefined) will be used.
If you want to call buildStuff with different callbacks, just do that, and eliminate the redundant setCallback:
function buildStuff(callback) {
element.onclick = function() {
doStuff(callback);
};
}
function doStuff(callback) {
callback();
}
function main() {
buildStuff(
function() {
//do something
}
);
}