I need to store an anonymous function passed as argument of my "named" function in Javascript, and then call it later.
How can I do this? I already know how to pass an anonymous function as an argument, but I don't know how to deal with it when I'm "on the other side" of the code.
Thank you
Functions in JavaScript are first-class members which means that you can work with them just as you would any other data type in the language - you can pass them as arguments, keep them as member variables inside of other functions, return them from functions etc.
In the case you've asked about, it works just like any other named variable with the neat addition that you can invoke the function as below since it is a function:
function myFunc(anonymous){
var arg1;
anonymous(arg1);
}
myFunc(function(arg1){console.log(arg1)});
Just call it using the name of the parameter.
function callThisLater(laterFunction) {
// ...
laterFunction(args);
}
callThisLater(function (arg1) {
alert("We've been called!");
});
Here is basic example:
function Foo(func) {
this.Func = func;
this.Activate = function() {
this.Func();
};
}
var foo = new Foo(function() { alert("activated"); });
foo.Activate();
I believe that what you missed is using the () to "activate" the function - as far as I understand you reached the point of "storing" the function to variable.
can you assign your anonymous function passed as an argument to a named function to a global variable inside the named function and then can used the global variable as a reference to anonymous function.
Related
What is the meaning of addHorizonLoadEvent(function() {...}) in the following snippet?
addHorizonLoadEvent(function() {
show_hide_datepickers();
});
addHorizonLoadEvent is a higher-order function -- that means it doesn't expect a non-function value (like a number, or a string) as it's argument, but another function. So the first argument is a new function, that will be called by the original function at some point (often at the end as a callback).
function() {...} is an anonymous function -- a way to express a function without binding it to a name.
This pattern is a called anonymous function.
function_name(function() {
// Code
});
Is the same as writing
function my_function() {
// Code
}
function_name(my_function);
Meaning that my_function is passed as an argument to the function function_name.
In fact you give a function as parameter of addHorizonLoadEvent.
You could do that :
var fooBar = function() {
//alert("Alert2");
show_hide_datepickers();
});
addHorizonLoadEvent(fooBar);
And the function parameter you give to addHorizonLoadEvent will be used only one time, no need to give it a name, so it is an anonymous function, directly declared in ().
Can someone clarify this point for me?
Two of my favourite features in JavaScript are closures and the fact that functions are first class objects.
If I want to take advantage of closure in, say, a callback function, then the function must always be an inner function. For example:
doNested();
function doNested() {
var message='Hello';
window.setTimeout(inner, 3000);
function inner() {
alert(message);
}
}
There is no way I can pass a parameter to an outer callback function. For example:
doSeparated();
function doSeparated() {
var message='Goodbye';
window.setTimeout(outer,3000);
}
function outer() {
alert(message);
}
This doesn’t work, of course.
The question is, is there any way to pass inner variables to an external function like this, short of adding them to a parameter list?
Thanks
If I want to take advantage of closure in, say, a callback function, then the function must always be an inner function.
That's correct. Every function in JavaScript only has access those variables which are either defined in its own scope or defined in a parent scope1. Therefore, your first example works while your second example doesn't.
The question is, is there any way to pass inner variables to an external function like this, short of adding them to a parameter list?
No, there's no way to do that. Well, technically you could add your inner variable to an object and then bind that object to the external function after which you can access the inner variable from the this context of the external function, but that is no better than passing the variable to the function directly.
doSeparated();
function doSeparated() {
var message = "Goodbye";
setTimeout(outer.bind({
message: message
}), 3000);
}
function outer() {
alert(this.message);
}
Since you are using setTimeout, you can pass extra arguments to setTimeout which will be given to the callback function. This gets rid of the nasty bind:
doSeparated();
function doSeparated() {
var message = "Goodbye";
setTimeout(outer, 3000, message);
}
function outer(message) {
alert(message);
}
Note that both bind and extra arguments of setTimeout don't work in older versions of IE. In that case, you can use currying instead (which in my humble opinion is the best solution aside from your original nested solution):
doSeparated();
function doSeparated() {
var message = "Goodbye";
setTimeout(outer(message), 3000);
}
function outer(message) {
return function () {
alert(message);
};
}
Other than these, there's no other good solution that I can think of. The best solution is your original nested solution.
1 A function doesn't have access to any variable defined in a child scope or else you would be able to access every variable from the global scope.
I'm currently trying to teach myself more about javascript, and I find myself stumbling over the syntax for passing a method as an argument to another method call. Say you have two functions like these:
function FirstFunction()
{
DoesSomething();
}
function SecondFunction(func)
{
func();
}
In actually passing the FirstFunction to the SecondFunction, I seem to see a wild variety of variations on doing so:
SecondFunction(FirstFunction);
or
SecondFunction("FirstFunction()");
or sometimes, if FirstFunction was defined as follows:
var thisisafunction = function FirstFunction()
{
DoesSomething();
}
SecondFunction(thisisafunction);
I'm guessing there's no "one right way" to do this, so when is it appropriate to use each way of passing a function? Is it better to use one way over another in a certain situation?
Passing a string is always bad. It only works with functions like setTimeout which automatically eval() strings and it's bad since it runs in the global context.
If you just want to pass a plain function without creating a closure or passing arguments, passing the function without () is fine:
myFunc(someCallbackFunc);
If you need to pass arguments or want a closure so you can access some non-global variables inside that function, use an anonymous function:
myFunc(function() {
someCallbackFunc('meow');
});
Of course you can also assign the function to a variable first:
var cb = function() {
someCallbackFunc('meow');
};
myFunc(cb);
While var cb = function someName() {}; is valid, I'd recommend against giving your function expressions names - it's not supported by all browsers. The only advantage is having a function name in debuggers anyway...
First let me clear something. You can define functions both as:
function name() { ... };
or assign it to a variable
var myFunc = function() { ... };
you don't mix both by doing
var myFunc = function name() { ... }; //WRONG
since name won't be binded to anything.
After this, the most usual way of passing functions as arguments, is just to pass the function object without the function call operator "()", which means the function object is not executed.
var func1 = function() { console.log("func1 here") };
var func2 = function(f) { f(); };
func2(func1);
Also, passing the function as String with the function call operator means that the receiving function will have to evaluate that using eval() for the function argument to be executed. It is not recommended.
The book Learning JavaScript defines anonymous functions as follows...
Functions are objects. As such, you can create them - just like a String or Array or other type - by using a constructor and assigning the function to a variable. In the following code, a new function is created using the Function constructor, with the function body and argument passed in as arguments:
var sayHi = new Function("toWhom", "alert('Hi' + toWhom);");
This type of function is often referred to as an anonymous function because the function itself isn't directly declared or named.
Is this the correct definition of an "anonymous function" in JavaScript? If not, what is an anonymous function, and is there any difference between an anonymous function and a function literal?
Function expressions and function declarations
Since you are interested in functions, here is some important stuff to know.
var abc = function() { ... } is known as a function expression. The variable will be assigned that anonymous function at execution time, though its variable declaration will be hoisted to the top of the current execution context (scope).
However, a function expression can be given a name too, so that it can be called within its body to make it recursive. Keep in mind IE has some issues with this. When you assign it a name, it is most definitely not an anonymous function.
A function such as function abc() { ... } is known as a function declaration. Its definition is hoisted to the top of its scope. Its name is available within it and its parent's scope.
Further Reading.
Your Example
It is an anonymous function, but assigned to the variable sayHi.
As Šime Vidas mentions, a new Function object is instantiated with the new operator, and the arguments and function body are passed in as strings. The resulting object is assigned to sayHi.
The real world use of creating a function using this method is rare (though it may be just to help show that functions are objects). I also believe passing its arguments list and function body as a string will invoke an eval() type function, which is rarely good when a much better construct is available.
Also, functions created with Function do not form a closure.
I would only use this method if for some reason I needed to create a Function with its arguments and/or body only available to me as a string.
In the real world, you'd do...
var sayHi = function(toWhom) {
alert('Hi' + toWhom);
};
Also refer to comments by Felix and Šime for good discussion and further clarification.
I think a broader and more accepted definition of an anonymous function is a function that is created without a name.
An anonymous function is simply a function with no name.
function(a, b){
return a + b;
}
The above code would be useless as it has no name to which you could call it with. So they are usually assigned to a variable.
var func = function(a, b){
return a + b;
}
This is helpful because you can pass an anonymous function to another function or method without having to create the function before hand, as demonstrated below.
function bob(a){
alert(a());
}
bob(function(){
return 10*10;
})
This:
new Function("toWhom", "alert('Hi' + toWhom);")
and this:
function(toWhom) { alert('Hi' + toWhom); }
are two expressions that produce the same result - they return a new anonymous function object.
The second expression (and only the second expression) is called a function expression. You may also call it a function literal (although we could argue that a function declaration is also a function literal).
function foo(){
alert("i'm foo, nice to meet you!");
}
var bar = function(){
alert("I am an anonymous function assigned to the variable \"bar\"");
}
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 ...