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.
Related
Can somebody explain me what (this) means at the end of the following code:
var a=(function(_this){
return function() {
//do something
return smth;
};
})(this);
What is the sense of such coding?
Going forward, what does the following code do, when placed in .js file and invoked by html tag?
(function() {
Emitter=(function(){
function Emitter() {}
...
return Emitter;
})();
A=(function(_super){...})(Emitter);
}).call(this);
how to instantiate object A from outside the js file?
This is a self-executing function, which is used to save a reference to "this" through the function's closure. It is used to hold on to the reference to "this" at the function's first execution time.
You can also use Function.prototype.bind() to achieve a similar result of saving a reference to "this":
MDN - Bind
This whole structure is a means of saving the current value of this so that a function call later on can use it.
That could all be done also with .bind() like this which (if you understand what .bind() does might be easier to follow):
function myFunc(_this) {
// do something
}
var a = myFunc.bind(null, this);
Here are the various steps in what happens in the code you've shown:
this will have a value from the surrounding context when this code is originally executed (which you don't show). It is being passed into a self-executing function as an argument often referred to as an IIFE (immediately invoked function expression) which is just a function call that happens immediately inline as the code is initially run.
Within that function it is given an argument name of _this.
When that function executes, it returns another function. The body of that inner function also has access to _this.
When that inner function is returned, it is assigned to the variable a.
The upshot of all this is that one can call a() and the internals of that function, when it executes will be able to access _this which contains the value of the original this.
So, it's essentially a means of creating a function that when executed will have access to the original value of this even though the context will have changed when a() is later called. So, its essentially saving the value of this for a specific function to use later.
More detail would require more context about what is going on inside that internal function, what the this value was in the original context and how a() is used later.
This is one particular use of an IIFE. They have many other uses.
I have always seen code like this:
(function(){
//code here
})();
How does this code work? Which function receives which parameters?
(function(factory){
//code here
}(function($){
//other code here
}));
function($){
//other code here
}
This block is passed as a parameter to the outer IIFE. It might be clearer to write it like this:
var factoryDef = function($) { ... };
(function(factory) {
// this is the outer IIFE
var someVar = {};
// you can call:
factory(someVar);
// the previous line calls factoryDef with param someVar
}(factoryDef));
So factory(someVar) is the same as factoryDef({}); the latter is simply the value of factory (which is the function factoryDef) called with the value of someVar (which is {}.)
Does that make sense?
Let's dissect:
Another way to look at this is:
Starts with an anonymous function declaration assigning within the function, the first parameter to be passed, the variable name "factory",
Then the anonymous function is immediately invoked, so far so good, often called IIFE, (or in this case D.C. calls "dog balls" ;) ).
Here's a twist, within the immediate invoking of the outer-most function another anonymous function is declared and passed as an argument. This, of course is referred to as "factory" within the outer-most function. And,
This inner-most anonymous function has as a named parameter "$". So I must anticipate the outer most function, when calling "factory", the inner-most function, will pass something to it which will be referred to as "$" in the inner-most function. For example: factory(jQuery);.
Actually when reading code I think it's best to start at the end and inner. So here the first thing I look at is the function with the "$". Looks like an anonymous function declaration. And it happens to be instantiated in a function execution. Moving out and left now. The function that is being immediately executed is also an anonymous function, not a problem because it's only called once and it's execution is built it. And our inner-most anonymous function get's a name in the outer-most function declaration. Finally wrapping the whole deal in parentheses is necessary to put the anonymous function in an expression context. If the first thing on the line is the word "function" then the function is in declaration context and the Javascript parser won't allow it to be immediately invoked. Oops.
Even more stretched out looks like:
var innerMost = function($) { console.log($); };
var outerMost = function(factory) {
var kaChing = 'baLing';
factory(kaChing);
};
outerMost(innerMost);
Voilà!
.
Fiddle with this: http://jsfiddle.net/xFnP7/1/
Much more here: http://benalman.com/news/2010/11/immediately-invoked-function-expression/
I've got a small drag and drop set up up and running, but it's using inline javascript and I'd prefer to move it all to an external file. Theoretically it's an easy swap, but I'm getting referenceErrors in my inspector and my minifcation is failing.
From what I can tell, the issue is coming from the return.
Original HTML
<section id="titles" ondrop="dropClip(this, event)" ondragenter="return false" ondragover="return false"></section>
Desired HTML
<section id="titles"></section>
JavaScript
var titles = document.getElementById('titles');
titles
.addEventListener('drop', dropClip(this, event))
.addEventListener('dragenter', return false)
.addEventListener('dragover', return false);
Javascript is a language where functions are "first-class objects". This means, possibly contrary to other programming languages that you may have experience in, that you can treat a function like any other object: you can pass it around, you can return it, you can have a function with a function inside it with a function inside it, and so on.
The consequence of this may be a very unexpected programming style required to be successful in Javascript. In other languages, UI event binding occurs in a variety of ways (such as C#'s Button1.Click += new System.EventHandler(this.myEventHandler);, or Classic VB's Button_Click()). In C#, you can pass around delegates, which are special objects with a specifically defined set of parameters and return values, to which a function can be bound. But all that disappears in javascript because you can simply attach a function to a property directly. For browser DOM event handling, the property is assumed to be a function reference, and during the native event handling code for that event, it calls the function attached to the property with the same name as the event.
Okay, you say, we have functions. And we can pass them around and treat them just like variables. Now what?
First, please take special note that the following two functions declarations are identical. They yield the exact same result, of declaring a function named myfun in the current scope (in a browser, the window object or the current function that is running).
function myfun(param1, param2) {
//do some stuff
};
var myfun = function (param1, param2) {
//do some stuff
};
(Actually, the first one will end up with a name property that the second one won't, and possibly some other minor differences, but for all practical intents and purposes they are identical).
The first one is just a shortcut for the second one. Basically, you create a function (that may or may not have a name) and assign it to a variable. Programmers use the convenient shortcut of calling the result "the myfun function", but in reality the case is "the myfun variable--which contains a particular function right now".
You can get many references to the same function--which is a true object--just by assigning it to other variables:
function myfun(param1, param2) {
//do some stuff
};
var a = myfun, b = myfun, c = myfun;
a(); // runs `myfun`
b(); // runs `myfun`
c(); // runs `myfun`
The next thing to notice is that to invoke a function, you must use parentheses after its name, and any parameters go inside the parentheses.
var result = myfun('a', 1); // invoke the `myfun` function
// and store its return value in variable `result`
But take a look back at our assignment statement making a, b, and c all be aliases of the myfun function: in those cases we didn't use parentheses, because--and here is where it gets really important, so pay attention:
To invoke a function (and get the function's return value), use parentheses after its name.
To pass a function reference, do not use parentheses.
What if we had done this instead:
var a = myfun(), b = myfun(), c = myfun();
a, b, and c would no longer be pointers to the myfun function. They would all be the result of myfun and would contain whatever myfun returned--or undefined if it didn't return anything. If you tried to invoke one of these, say a() you would get some error similar to:
> TypeError: a is not a function
Now that I've painted all that background, there is one simple thing to know that will get you on track to being successful with addEventListener: it expects a function as the second parameter. In your example code, you've put the contents of functions you'd like to run when addEventListener calls them, but no actual functions.
You can solve that by actually declaring the functions first, such as:
function doNothing() {
return false;
}
titles.addEventListener('dragenter', doNothing);
// Note: this is not invocation like `doNothing()`, but passing a reference
Or, you can simply wrap your function statements into an anonymous function. Remember, functions in javascript don't actually have names, we just have variables that contain functions. An anonymous function is one that has no name at all, and it is invoked either by an implicit name assignment (such as being passed as a parameter--where it will have the parameter's name) or by being directly invoked by doing the magic invocation action of putting parentheses after it.
That would look something like this:
titles.addEventListener('dragenter', function () { // anonymous function
return false;
});
If you want to invoke an anonymous function, you do have to let javascript know you want to treat it like a value as opposed to the normal shortcut-method of creating a named function in the current scope (where function myfun is treated like var myfun = function). That is done by wrapping the entire thing in one more set of parentheses, like this:
(function () { // begin a function value containing an anonymous function
// do something
}()); //invoke it, and close the function value
I hope this helps you understand more about javascript, why your code was not working, and what you need to do to make it work.
For sure you have to wrap the function contents you give to addEventListener into a function.
For instance instead of .addEventListener('drop', dropClip(this, event)) you will write .addEventListener('drop', function(event) { dropClip(this, event); })
When I make an anonymous function in JavaScript like this:
(function(){
/* some code here */
})()
In which object will be this function added, and where will this function live?
Also you can see in the jQuery source code an anonymous function like this:
(function(window, undefined){
/* some code here */
})(window)
How do this function's arguments differentiate it from an anonymous, 0-arg function?
Functions in JavaScript are values. That is, a function is represented by an object, and like any other object it can be the value of a variable or participate in expressions.
Thus
(function() { ... })
is a value, just like 17 or "hello world" is a value.
When a function (as a value) appears in an expression, and it's followed by (...) with a comma-separated list of expressions between the parentheses, that's a function call.
OK, so:
(function() { ... })()
creates a function (as a value) and then invokes that function with no arguments. The function object, at least as a direct result of that code, is not stored anywhere. It essentially vanishes after the function call completes, and the overall value of that subexpression will be whatever the function returned.
Passing parameters to such a function is no different than passing parameters to any other function. In the specific example you quote, the purpose is to prevent certain kinds of anomalies caused by errant "alien" code. Your example really should read:
(function(window, undefined) {
// code
})(this);
The symbol this is a reserved word and its value is under complete control of the runtime. (Well, it's value in a local execution context is thusly controlled.) When evaluated in the global scope, the above code ensures that inside the anonymous function, the symbol "window" will be a reference to the global context. That sort of construct is also useful for code that may be used in contexts other than a browser, like Node.js for example, where the global context isn't called "window".
Both examples you gave are anonymous functions, according to the first line of the Wikipedia definition:
an anonymous function [...] is a function (or a subroutine) defined, and possibly called, without being bound to an identifier
The arguments do not make a difference with respect to anonymity. Anonymous functions can take 0, 1, 2, ... n arguments, just like non-anonymous functions (i.e. named functions).
One major advantage of anonymous functions is that they don't have to live anywhere -- they can be defined and used inline, just like other values of other types.
Adding to #Pointy's answer adding parameters to an anonymous function doesn't make any difference
(function(){
/* some code here */
})()
(function(window,undefined){
/* some code here */
})(window)
Both the functions are lost after they are called, the only difference is that inside the second function some variables or functions are being stored in window context, but the anonymous function in itself is lost after the call.
If you need to keep the reference to the function try
(window.myFunc = function(arg1, arg2, arg3) {
/* your code here*/
})(arg1, arg2, arg3)
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 ...