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 ().
Related
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();
});
});
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.
Based on some code in a lecture by Doug Crockford, I've created this.
var isAlphaUser = (function() {
alert("Forming Alpha User List");
let AlphaUsers = {
1234: true,
5678: true
};
return function(id){
alert("Checking Alpha Users:",id);
return AlphaUsers[id];};
}());
alert("starting");
alert(isAlphaUser(1234));
alert(isAlphaUser(5678));
alert(isAlphaUser(3456));
which gives me this:
Forming Alpha User List
starting
Checking Alpha Users: 1234
true
Checking Alpha Users: 5678
true
Checking Alpha Users: 3456
undefined
Which is quite cool, as it does the expensive setup once only, and every further call is a cheap check.
However, I can't decipher the code that does this. Specifically, I can't understand why I need the "()" at the end of the function declaration.
Can somebody explain how this syntax is working?
() calls a function. function() { } defines a function. Appending () right after immediately calls it1, and the result (also an anonymous function) is assigned to isAlphaUser.
The function() { ... }() pattern is frequently used to isolate variables to an inner scope, so those variables don't become part of the global scope.
In this case, this is what happens:
An anonymous function is run, defining a variable AlphaUsers inside that scope.
That function returns another function that takes 1 parameter. This function is a closure to which the AlphaUsers variable becomes bound (in other words, available). This function checks if the parameter passed in is contained in AlphaUsers (actually, it returns the item at that index, which is just a boolean).
The return value is assigned to a variable isAlphaUser.
Since isAlphaUser is now a function, it can be called to see if the parameter is contained in the AlphaUsers variable, but no direct access to AlphaUsers is available in the global scope (it become a sort of private variable).
1 — Note: As cwolves mentioned in the comments, beware that while () appended directly after the } works in this case, it is only because in this case the function definition is a function expression. If function is the first word on the line, the line becomes a function declaration, and that is all that line can do, the function is not anonymous (it will require a name, otherwise it's a syntax error) and cannot be called immediately inline. See Function Declarations vs. Function Expressions for more info.
The () at the end of the code is separate from the closure issue. By wrapping your function in parens and adding the () at the end you are creating an anonymous function that is run immediately with whatever arguments you pass into ().
Specifically, I can't understand why I need the "()" at the end of the
function declaration.
It creates self-invoking function, in other words, the function is executed as soon as it is parsed.
It is basically same thing when you call a function by suffixing it with () like:
myfunc(); // call this func
The top-level anonymous function returns the function that the isAlphasUser varaible refers to.
You need to call the top-level function, to get the inner-function reference.
Think of it like this, the outer anonymous function is a function factory, i.e., it returns a function.
In order to use any function (even one that returns a function) you must call it.
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.
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 ...