If I have the code below, where I pass two functions as a parameters into the function sayHi, is this an example of a callback?
I notice there are two ways of running these 'parameter functions': either as below, we I call the functions where they are defined (as arguments), or alternatively where I call the parameter in the sayHi function. Would this be the difference between a callback and an anonymous function?
function sayHi(name, testForTrue) {
if (testForTrue == true) {
console.log(name);
}
}
sayHi(function() {
return 'Zach'
}(), function() {
return true;
}());
Another way I could get the same result, is as below. In this case I am evaluating the functions at a different time? Is there any practical difference between the two?
function sayHi(name, testForTrue) {
if (testForTrue() == true) {
console.log(name());
}
}
sayHi(function() {
return 'Zach'
}, function() {
return true;
});
Yes, functions passed as parameters are always callbacks, even if the intention is that the function is called synchronously (c.f. Array.prototype.map) rather than asynchronously (c.f. window.setTimeout).
In your first code block you aren't of course actually passing functions. You have two immediately invoked function expressions, where the key part in this context is immediately invoked. The function expressions are called at the point they appear in the code and only the results of those expressions are passed to sayHi.
In your first example you're not passing functions, but values; in other words
(function(){ return 3; })()
is just the integer 3.
It is a value obtained calling immediately a function, but this is irrelevant.
When you pass a callback it's the receiver that will call it (or pass it to some other function) and the code will be executed later, and not at the call site.
I guess that would depend on what your callback function is actually doing.
In your examples, all you're really doing is returning a value. That's not really a "function", it's returning one fixed value every single time.
If your function is actually doing a process, or returning a varied result, then I would personally consider it a callback. (The name of it is self-explanatory, really). Your script shouldn't rely on it, rather have it be a handler for the result of the function.
For instance, something like this would be what I consider a callback function:
function doSomething(callback) {
var userInput = prompt("hello, enter a number 1-10"),
hasWon = false;
if (userInput === "3") hasWon = true;
callback(hasWon);
};
With this provided, we can call it like this:
doSomething(function(hasWon){
if (hasWon) alert("Congratz! You guessed my lucky number!")
});
Related
Is it in PHP possible to pass a executed function as function's parameter, so that the result of the function will be hand over but not a callback function object?
Without touching the scope function (no eval or extra magic execution).
Let's say, the parameter I want to give the function is not clear. So there must be a decision for that before given to the function.
Currently this always lookes like this:
$tmp = ($something == $bla)?42:7;
myFunction($tmp);
For such a short decision it is not so problematic. But sometimes there are more then two possibilities. So a if-elseif is needed, or a switch-case.
But it would be so much cleaner to just put somthing like this:
myFunction(function(){
if(...){ return 42; }
elseif(...){ return 7; }
elseif(...){ return 5; }
elseif(...){ return 12; }
else{ return 1; }
});
So without saving it first to a variable.
Just for cleaner code, less $tmp or $trash variables.
Anonymous functions and variable functions should be what you are looking for:
Anonymous functions, also known as closures, allow the creation of
functions which have no specified name. They are most useful as the
value of callback parameters, but they have many other uses.
Anonymous functions are implemented using the Closure class
And a code example:
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
And one more code example, just for the sake of completeness, about how to pass a function name as parameter, and call it aftwerwards:
<?php
function here() {
print 'here';
}
function dynamo($name) {
$name();
}
//Will work
dynamo('here');
//Will fail
dynamo('not_here');
Last example was extracted from here
So with the understanding of anonymous functions (Thanks Lucas Meine ), I found that you can execute a function directly by surrounding it with brackets, followed by parameter brackets that will be empty or not depending on whether you want to give the lower level function some of your variables out of the main context.
In all following examples the output of var_dump is 42.
example without variable parameters
// the function that should later be called
function myFunction($test){
var_dump($test);
}
// function call with a executed function as parameter
myFunction((function(){
return 42;
})());
example with variable parameters
$someVar = 42;
function myFunction($test){
var_dump($test);
}
myFunction((function($tmp){
return $tmp;
})($someVar));
or with the use statement
$someVar = 42;
function myFunction($test){
var_dump($test);
}
myFunction((function() use ($someVar){
return $someVar;
})());
onHangeChangeQuanity = (opr) => {
let { number } = this.state;
if (opr === '+') {
this.setState({ number: number+1 }, this.onSubmit);
} else if (opr === '-' && number !== 0) {
this.setState({ number: number-1 }, this.onSubmit());
}
}
onSubmit = () => {
let { attributeName, typeOfField } = this.props.attribute;
let { number } = this.state;
let attr = { attributeName, typeOfField, selectedValues: [ number ] };
this.props.onHandle(attr);
}
In the above example in my if condition (opr === '+') I call my onSubmit func without parentheses and it works find and show the current state of my number but in the else condition (opr === '-' && number!==0) I use onSubmit() with parentheses in my setState callback and it doesn't update the state like it should.
Can someone please explain the difference between a javascript function that is being called with and without parentheses.
Thankyou.
Because setState is not guaranteed to be synchronous, it accepts a callback function as the second argument, which it will call after it has updated the component's state.
There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.
Passing the function as a reference (without parentheses) ensures that your onSubmit method will only be called after the component's state has updated and you can rely on this.state to contain the new value.
Calling the function yourself (with parentheses) means that your onSubmit method will always execute before this this.state has the correct value, because it will run before setState does. If this is intentional behaviour it may make more sense to write it explicitly.
this.onSubmit()
this.setState({ number: number-1 });
Without parentheses you only access to it's reference. You can use it to pass the reference for example into another function or use it's properties, because every function is also an object. Look at an example
function first(){
console.log('first');
}
function second(func) { // this get an parameter which is a function
func(); // And here I call it
}
second(first); // Here I pass the function's reference
// And actually call the second with parentheses
With parentheses you execute the body of that function
With the parentheses, you are writing a function call. Without them, you are simply "referring" to the function.
A function call just executes the contents of the function and may or may not return a value. A function reference can be used juts like any other variable. You can pass it to other functions, assign it to another variable etc.
Why are function references useful?
Some functions, like window.setTimeout, take function references as parameters.
window.setTimeout(someFunc, 1000);
Here someFunc will be executed after 1 second. You don't add the parentheses because what you're saying is "I want this function to be called after some delay". Adding parentheses here would have called the function immediately.
Calling a function without parenthesis is referring to the function not what it returns, it is just like assigning and calling it with parenthesis is calling the value of that method, the body of the function executes and may return the required.
When a function name is followed by parenthesis, it is like we say I want to call the function. While when you pass in one or another place a function name, you just pass a copy of the reference to the function.
function sayHello(){
console.log('Hello');
}
// Here we call sayHello();
sayHello();
function executeAnotherFunction(func){
// We request the execution of the function passed.
func();
}
// Here we pass a reference of sayHello to executeAnotherFunction
executeAnotherFunction(sayHello);
My html contains two forms overlapping each other, one used as add form and one as edit form. I use jQuery to show and hide them with the following code:
var editForm = $("#edit-form");
var addForm = $("#add-form");
var showEditForm = function() {
editForm.fadeIn(function() {
addForm.fadeOut();
});
};
var showAddForm = function() {
editForm.fadeOut(function() {
addForm.fadeIn();
});
};
I wanted to make the code more compact so I set the fadeOut() call directly on the fadeOut() callback by doing like this:
var showEditForm = function() {
editForm.fadeIn(addForm.fadeOut);
};
var showAddForm = function() {
editForm.fadeOut(addForm.fadeIn);
};
But this productes the following error Uncaught TypeError: Failed to execute 'animate' on 'Element': Valid arities are: [1], but 4 arguments provided. but why doesn't that work?
That's because calling a function as a property of an object is a special syntax, that calls the function with the object as context.
When you call a function like this:
obj.func();
then this will be a reference to obj inside the function.
If you get the reference to the function, and then call it:
var f = obj.func;
f();
then this will be a reference to the global context, i.e. the window object.
By using editForm.fadeIn(addForm.fadeOut); you get the reference to addForm.fadeOut and send to the fadeIn method. It's no longer associated with the object, so it will be called with the global context instead of the object as context.
You can use the proxy method to associate the function with the object, so that it will be called with the correct context:
var showEditForm = function() {
editForm.fadeIn($.proxy(addForm.fadeOut, addForm));
};
var showAddForm = function() {
editForm.fadeOut($.proxy(addForm.fadeIn, addForm));
};
I suspect the problem is that addForm.fadeOut is being called with a bad combination of arguments, when its passed to the fadeIn function (and vice versa).
The classic example of this pitfall seems to be:
["0", "1", "2", "3"].map(function(i) {return parseInt(i);})
This, works as expected and gives [1,2,3,4] as a result. You might expect that you could shorten this, much as you did above, and write
["0", "1", "2", "3"].map(parseInt);
Unfortunately; this evaluates to [0, NaN, NaN, NaN]. The problem, is that .map calls any function provided it with three arguments: the value, the index, and the array itself, and parseInt takes up to two arguments: the value, but also the radix/base to parse in. (e.g. radix 2 to parse a string as binary) So what actually happens is essentially:
[
parseInt("0", 0), //0, radix is ignored
parseInt("1", 1), //NaN, what is base 1?
parseInt("2", 2), //NaN, 2 isn't valid binary
parseInt("3", 3) //NaN, 3 isn't valid ternary/base-3
]
I suspect, based on the error message, that the same thing is going on here. The "arity" of a function is the number of arguments passed to it, so the error message here says that 4 arguments were provided, when only one was expected.
In general with functions that take optional arguments, you need to be careful before passing them to other functions directly, or else you can't control what arguments it will be called with.
Fiddle: http://jsfiddle.net/jmj8tLfm/
addForm.fadeIn and addForm.fadeOut are being called without specifying the this context that would normally be passed when you call addForm.fadeIn(). Try .bind()-ing the this variable appropriately as follows:
var showEditForm = function() {
editForm.fadeIn(addForm.fadeOut.bind(addForm));
};
var showAddForm = function() {
editForm.fadeOut(addForm.fadeIn.bind(addForm));
};
If you are writing in vanilla js. The reason as to why you need too pass the callback function in an anonymous function has to do with function invocation.
Take a look at this example:
const firstFunc = (callback) => {
setTimeout(function() {
console.log('yes');
console.log(callback())
}, 3000);
}
const secondFunc = () => console.log('great');
firstFunc(function(){
secondFunc();
});
// prints 'yes' 'great' after 3 seconds
> yes
great
When invoking the function, if you pass the callback argument without the parenthesis i.e firstFunc(secondFunc); the callback function will invoke after the first function has finished (just like above) provided inside the first function where the callback gets called is invoking that function. i.e callback(), the () is the important part.
Try omitting the parenthesis inside the first function like this, callback and pass the second function as a callback without the parenthesis firstFunction(secondFunction) notice how you are passing the callback function but it is never being invoked. Your console.log() should look like this.
> yes
() => console.log('great')
So why does this matter...
If you pass the function invocation as firstFunc(secondFunc()) using the setup from the first code snippet. You will notice that the second function prints first then 3 seconds later the first function is invoked.
> great
yes
Given that Javascript is event driven, the invocation of the second function can be found const secondFunc = () => console.log('great'); and it will immediately invoke that function not waiting for the response from the first function. That is what the () did when you invoked secondFunc() inside firstFunc.
By passing an anonymous function that function is never being invoked until it reaches the callback() invocation part. Again using the setup from the first code snippet, try.
firstFunc(function(){
secondFunc();
});
firstFunc(function(){
secondFunc();
}())
See how the second call invokes the secondFunc right away. What is happening is the anonymous function is a wrapper to not invoke your function right away.
Why is this useful?
If secondFunc takes a callback that callback function would not be invoked until the second function has finished executing. You would need to call that callback function inside your second function.
firstFunc(function(){
secondFunc(function(){
thirdFunc();
});
});
Is it possible to assign a whole line of code to a function parameter? Take this example:
function testFunc(parameter1){
parameter1;
}
testFunc($(".someClass").text("someText"));
When the function is used with that parameter, can the parameter1 be replaced by the line of code?
I'm new with JavaScript and jQuery, so I'm just curious if this is possible. I did not see any questions like this asked before. But if it was asked, a link to the question would be appreciated. Thanks
Sounds like you are inventing the callback :)
Pass an actual function and call it with ();
function testFunc(callback){
callback();
}
testFunc(function(){$(".someClass").text("someText");});
Yes it can be done , as jQuery will eveluate it and return a object.
The key insight here is that a function can be treated like any other variable.
For example:
var i = 1;
var f = function() { console.log('hello!'); };
Here f is a value, just like i is, but you can invoke it just like any other function:
f(); // prints 'hello!' in the console
Because it is a value, you can pass it to another function:
function g(h) { h(); }
g(f); // prints 'hello!' in the console
Take the time to ensure you understand the above code. I've deliberately used vague names so you can learn the mechanics. Let me know if you have any questions.
Arguments aren't assigned to functions, they are passed/sent/[insert other synonym here].
Anything that is an expression (any code which evaluates to some value) can be passed around.
In your exemple $(".someClass").text("someText") is an expression which evaluates to a jQuery object, so you can use this unit of code as a function's argument without any doubt.
However, if you want to pass around some code which has to be executed as part of an existing function's process, you must use a function expression which encapsulates that behavior.
E.g.
function executor(task) {
task();
}
executor(function () {
//code to be executed by the executor
});
Yes you can pass function callback like regular primitive variable
In your case you should check param type before execution
function testFunc(parameter1){
if(typeof parameter1==="undefined"){
//arguments[0] will fall here
console.log("No arguments case. parameter1 not defined")
}
else //function check
if(typeof parameter1==="function"){
//you can parameter function here.
return parameter1();
}
else{
//regular case value or object, other than function types fall here
console.log("not a function, received param type: "+ typeof(parameter1));
return parameter1;
}
}
$(function (){
//let us say you have below vars
var primitiveVar="test",
fun = function(){console.log("function fun call")};
//no args here
testFunc();
//sending primitiveVar
testFunc(primitiveVar);
//below is your call with jQuery Obj
testFunc($(".someClass").text("someText"));
});
Now, I usually call a function (that requires no arguments) with () like this:
myFunction(); //there's empty parens
Except in jQuery calls where I can get away with:
$('#foo').bind('click', myFunction); //no parens
Fine. But recently I saw this comment here on SO:
"Consider using setTimeout(monitor, 100); instead of setTimeout('monitor()', 100);. Eval is evil :)"
Yikes! Are we really eval()-ing a string here? I guess I don't really understand the significance and implications of 'calling' a function. What are the real rules about calling and referring to functions?
In JavaScript functions are first-class objects. That means you can pass functions around as parameters to a function, or treat them as variables in general.
Let's say we are talking about a function hello,
function hello() {
alert('yo');
}
When we simply write
hello
we are referring to the function which doesn't execute it's contents. But when we add the parens () after the function name,
hello()
then we are actually calling the function which will alert "yo" on the screen.
The bind method in jQuery accepts the type of event (string) and a function as its arguments. In your example, you are passing the type - "click" and the actual function as an argument.
Have you seen Inception? Consider this contrived example which might make things clearer. Since functions are first-class objects in JavaScript, we can pass and return a function from within a function. So let's create a function that returns a function when invoked, and the returned function also returns another function when invoked.
function reality() {
return function() {
return function() {
alert('in a Limbo');
}
};
}
Here reality is a function, reality() is a function, and reality()() is a function as well. However reality()()() is not a function, but simply undefined as we are not returning a function (we aren't returning anything) from the innermost function.
So for the reality function example, you could have passed any of the following to jQuery's bind.
$('#foo').bind('click', reality);
$('#foo').bind('click', reality());
$('#foo').bind('click', reality()());
Your jQuery bind example is similar to setTimeout(monitor, 100);, you are passing a reference of a function object as an argument.
Passing a string to the setTimeout/setInterval methods should be avoided for the same reasons you should avoid eval and the Function constructor when it is unnecessary.
The code passed as a string will be evaluated and run in the global execution context, which can give you "scope issues", consider the following example:
// a global function
var f = function () {
alert('global');
};
(function () {
// a local function
var f = function() {
alert('local');
};
setTimeout('f()', 100); // will alert "global"
setTimeout(f, 100); // will alert "local"
})();
The first setTimeout call in the above example, will execute the global f function, because the evaluated code has no access to the local lexical scope of the anonymous function.
If you pass the reference of a function object to the setTimeout method -like in the second setTimeout call- the exact same function you refer in the current scope will be executed.
You are not doing the same thing in your jQuery example as in the second setTimeout example - in your code you are passing the function and binding the click event.
In the first setTimout example, the monitor function is passed in and can be invoked directly, in the second, the sting monitor() is passed in and needs to be evaled.
When passing a function around, you use the function name. When invoking it, you need to use the ().
Eval will invoke what is passed in, so a () is required for a successful function invocation.
First of all, "()" is not part of the function name.
It is syntax used to make function calls.
First, you bind a function to an identifier name by either using a function declaration:
function x() {
return "blah";
}
... or by using a function expression:
var x = function() {
return "blah";
};
Now, whenever you want to run this function, you use the parens:
x();
The setTimeout function accepts both and identifier to a function, or a string as the first argument...
setTimeout(x, 1000);
setTimeout("x()", 1000);
If you supply an identifier, then it will get called as a function.
If you supply an string, than it will be evaluated (executed).
The first method (supplying an identifier) is preferred ...