Crockford had this example to keep myArray from being in the global scope:
var myName = (function() {
var myArray = ['zero','one','two','three','four'];
return function(X) {
return myArray[X];
}
}()); // This function is invoked immediately
result = myName(3); // Now invoke it "for real"
Q: I don't get why it isn't
var myName = (function(X) {
Q: When I call myName(3), isn't "var myArray=" executed a 2nd time?
Suppose it's not executed a 2nd time because JavaScript knows that it's already been defined... What about a loop or some other logic between the var stmt and the return function stmt? Wouldn't it be executed every time?
Q: Can you name the subfunction and call it instead of calling myName?
okay, let's break this down...
var myName = (function(){
...
}());
that piece sets myName to whatever that anonymous function returns, so if it were:
var myName = (function(){ return 42; }());
myName would equal 42. If that doesn't make sense, this is the same thing:
function someFunction(){ return 42; }
var myName = someFunction();
So in your example, myName is set to function(X){ return myArray[X] }. So myName is a function. When you call it, the only code that is run is return myArray[x]. myArray is kept in what is called a closure, it is only exposed to the myName function and the anonymous one surrounding it.
I wrote an article on closures years back that may help you: http://www.htmlgoodies.com/primers/jsp/article.php/3606701/Javascript-Basics-Part-9.htm (scroll down to the "Closures" header).
OK here it goes ..
answer to Q1 . it is not myName = (function(x) because the part inside the brackets returns a function which takes X . i.e. myname is not assigned to (function(){}) but to the return value of it .
Q2. No when u calll myName 2nd time it already points to the inner function hence the outer function is not invoked at all .(this is the sepciality of closures where the value stays alive in inner function even if outer functions are completed.)
Q3. Well nopes we can name the inner function but the name will be valid only inside the outer function and since outer function has completed the name would be useless.
The outer function doesn't have to have an argument X, because it's only purpose is to return another function (which then is parametrized). Thus no argument is needed here.
Thus the only effect is to bind the function(X)... thing to the variable myName. Therefore no other constructs like loops or so does make sense here.
Q1+2: Note the () right of the comment "This function is invoked immediately". The outer function defined is not stored in myName, but immediatly called. Itself then returns an anonymous function which has no name and requires a single parameter (X). This function beeing returned is stored in myName.
To grasp closure you should start thinking about functions just as another value of a variable which can be stored and returned jsut as any other value.
Q3: myName is the subfunction.
Okay answer in turn:
First, why it's var myName = (function() { and not var myName = (function(x) {
In this case because the x value isn't required to create the function you are returning. The data structure of the array contained in the returned function is hard coded and so you don't need additional information to construct it. Much in the same way that
function a() {
return 1 + 2;
}
Doesn't have any arguments, because it's values are hardcoded. This is an example of functions as data or first class functions
Question two: is var myArray executed every time.
The short of it is no. myArray has been assigned to at this point so it has a value that the system has already calculated. In this case it's a function. The myArray potion has been set and so there is no cause to keep executing it. If the outer function didn't return a new function then yes it would need to get called again and again but that would defeat the purpose of this abstraction.
Question three: can you call the inner function.
No, it's out of scope. The entire point of this example is that you have defined a function generator.
Answer to first question:
no, the first "line" is returning a function so when you call "myName" you are actually executing the returned function
function(X) {
return myArray[X];
}
Answer to second question
no, such a function can still refer to the array "myArray"... in fact the purpose of this closure is to make myArray available in the global scope
In words:
myName is the result of an immediately executed anonymous function. It returns a function reference (to an anonymous function). That function has one parameter: X. After execution of the topmost anonymous function, myName is a reference to the inner anonymous function.
Now the inner anonymous function has access to myArray via a closure (myArray and the returned anonymous function both live within the scope of the topmost anonymous function). So if you execute myName, you actually execute the inner anonymous function, which can access myArray.
The topmost anonymous function is executed immediately and once (it returns a reference to the inner function). So myArray is declared within that execution context, and only once.
Since the definition of the myName object (function) ends in '()', its function is called immediately, returning a new function which has the myArray variable statically bound to it. myName is then accessible globally but myArray is not as it is within a function closure. When you reference myName() it has exclusive access to the bound array.
This approach ensures that myArray is only allocated once, when the outer function 'is invoked immediately'. After it is invoked, myArray isn't in the global scope, but is still available to the anonymous inner function.
The approach you proposed would work, but would require that the array be allocated each time the function was called. (Or be allocated outside the function, in the global scope.)
Related
I am just getting more into javascript and wandering what is the difference between
var myfunc = function(){
publicfunctions = {}
publicfunctions.function1 = function(){do smthing and return}
return publicfunctions
}
and
var myfunc = function(){
this.function1 = function(){do smthing and return}
}
It seems to me that both doing the same thing
Also can someone explain what is difference between
var func = (function myfunc(){ .. do smthing and return .. })();
and
var func = function myfunc(){ .. do smthing and return .. }
var newfunc = new myfunc()
Thanks
Let's go step by step.
example:
a) you define a function that returns an object (careful with variable declaration - you should declare it with var keyword in order to scope it to your function. That objects has a single property that points to a function. Never the less, your first function is assigned to a variable myfunc
Now, if you try to call myfunc(), you'll get an object with single property function1. Nothing special here.
b) you define a function again and assign it to myfunc variable, only this time it contains this keyword which assumes you're trying to utilize this function as a constructor. In this example, merely calling myfunc produce no output since you haven't returned anything from a function. However, calling a function with preceding keyword new will result in object creation.
var myObj = new myfunc();
// `this` keyword now refers to myObj which means myObj can call `function1`
example:
a) On the righthand side is something that is called IIFE (or Immediately Invoked Function Expression). Basically means, a function expression that is created and executed, well, immediately. So func should receive whatever that function returns.
b) Yet again, facing a constructor, only this time you actually assumed myfunc is a constructor when you added new keyword before myfunc execution. Creates an object to whic newfunc now points to and has authority over.
Note:
In constructor functions (the ones that you call with new keyword), this is implicitly returned and no need for explicit return. Now, if you want to test it and return something else instead, I'll leave it up to you to explore and see what you'll end up with. :)
Since it's a broader topic in itself, I recommend this excellent book by Nicholas Zakas. It really answers a lot of JS questions.
I'm following a tutorial by Tyler McGinnis on execution contexts, call stacks and closures.
https://www.youtube.com/watch?v=Nt-qa_LlUH0&feature=emb_title
I'm a bit confused with the closure example. I understand a closure is when a function is inside another function. I also understand that the inner function has access to the parent functions arguments (As explained in the video).
My confusion is in the code below is when makeAdder(5) is invoked is the inner function not invoked aswell on the first invokation? Tyler appears to suggest makeAdder is popped off the call stack when first invoked just leaving the inner function untouched.
The second part I don't understand when we call add5(2) this is invoking makeAdder(5) no? How do we add 2 arguments when the parent function only accepts one?
If someone could walk it through step by step of how it's all invoked that would be great!
var count = 0;
function makeAdder(x) {
return function inner(y) {
return x + y;
}
}
var add5 = makeAdder(5);
console.log(add5); // what the call to makeAdder returns
count += add5(2);
console.log(count);
when makeAdder(5) is invoked, is the inner function not invoked as well on the first invocation?
No, it isn't. Only makeAdder is invoked at that time, and makeAdder is not making any calls itself. It merely returns an object, and that object happens to be a function. And returning a function is done without actually invoking it.
when we call add5(2) this is invoking makeAdder(5) no?
It is not invoking makeAdder(5). Earlier on add5 was the result of calling makeAdder(5), and so add5 is that inner function. The special thing happening here is that when you call add5, an "execution context" is restored, which represents the state of affairs inside makeAdder at the moment it returned the function. This practically means that when add5 (the inner function) references the x variable, it will find the value in x it had at the moment makeAdder had been called earlier on.
How do we add 2 arguments when the parent function only accepts one?
Indeed, when we call the parent function, the second argument is not known yet, and we don't need to know it at that moment, since the inner function is not yet executed at that moment. The important thing with the call of the parent function, is that we establish the value of x, which will "live on", even though it can only be accessed by calling the inner function.
And when we call the inner function, we provide the second argument that is needed. The inner function can then combine the "magical" reference it has to the x value (provided when we made the parent call), with the normal argument it receives itself.
A simple way to look at this is as a function that returns a function--which can be called like a normal function because it is. So the first call of the function return type is a function.
Look the following example
function add(x,y){
return x+y;
}
function subtract(x,y) {
return x-y;
}
function calculator(type){
if(type ==='add'){
return add ; //here we are returning a function - the above add function
}
if (type==='subtract')
{
return subtract; // we are returning a function - the above subtract function
}
return null;
}
var fn = calculator('add'); // this call will return the function add which can be called as in below
var result = fn(4,5);
console.log(result) ; ///should print 9
Likewise the first call
var add5 = makeAdder(5);
returns a function which is exactly
function inner(y) { return x+5);
Then you can call add5(2) which essentially execute the above function.
How the variable 'str2' is available inside the callback method passed to display method?
str2 should be visible only inside function 'name'.
a = {
display: function (n){
console.log("I am inside display method");
n();
}
}
function name(a,str2)
{
a.display(function (){
console.log(str2);
})
}
name(a, 'ddd');
Variable scoping in Javascript is hierarchical. Lower scopes have access to all variables of all higher scopes. Here's an example:
function outer() {
var foo = 2;
function inner() {
console.log(foo); // 2
}
}
It doesn't matter if a variable is passed as a parameter or if it was defined as a local var.
Yes str should be visible only inside function 'name' yes it is working same you said, in JavaScript function declarations loads before any code is executed, and scope depend on execution context
in your code scope of str2 is inside name() function and you call a.display() within this scope (within scope of name()) that's why str2 available inside display() at the time of execution.
To evaluate name(a, 'ddd'), the compiler will create a new stack frame and place two slots on it, one a, which will be a reference to the global object of the same name, and str2, which will contain the string literal 'ddd'. Then the body will be evaluated.
In the body, to evaluate a.display(function(){...}), the value of a.display will be resolved to the function with parameter n. To evaluate n(function(){...}), a new stack frame will be created with n assigned to the closure that results from evaluating the anonymous callback (a closure being a combination of a pointer to the static scope of the function and the compiler generated code for the function itself). Then the body of the a.display function will be evaluated.
In the body, the console.log will be called with the given string. Then the callback n() will be evaluated. Since n doesn't take any parameters, it will just be evaluated in the topmost stack frame, so when the time comes to evaluate console.log(str2), str will not be found on the current stack frame, so the compiler will follow the scope chain all the way to the frame where we bound 'ddd' to str and a to the function.
That's a pretty long answer to your simple question. I'll try to shorten it later. Also, corrections are welcome, as I'm being very hand-wavy with the evaluation process.
In Javascript the variable declared on a certain scope is available in every inner scope. In this case it's a concept called "closure". This answer might give you good insight about scoping in Javascript: What is the scope of variables in JavaScript?
Hope this simple example can help you understand its usefulness:
function counter () {
var votes = 0;
this.upvote = function() { votes++; }
this.downvote = function() { votes--; }
this.getValue = function() { return votes; }
}
var counter1 = new counter();
counter1.upvote();
console.log(counter1.getValue()) // Prints 1
counter1.upvote();
counter1.upvote();
console.log(counter1.getValue()) // Prints 3
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.
The following program returns "local" and, according to the tutorial Im reading, it is designed to demonstrate the phenomenon ofclosure`
What I don`t understand is why, at the end, in order to call parentfunction, it assigns it to the variable "child" and then calls "child."
Why doesn`t it work by just writing parentFunction(); at the end?
var variable = "top-level";
function parentFunction() {
var variable = "local";
function childFunction() {
print(variable);
}
return childFunction;
}
var child = parentFunction();
child();
parentFunction() returns another function which you assign to var child. Then, you call child() to invoke the function returned by the call to parentFunction().
Running just parentFunction(); at the end wouldn't do anything useful because you would just discard its return value which is a function. But this would work:
parentFunction()();
See this fiddle: http://jsfiddle.net/USCjn/
Update: A simpler example:
function outer() { // outer function returns a function
return function() {
alert('inner function called');
}
}
x = outer(); // what is now in x? the inner function
// this is the same as saying:
// x = function() {
// alert('inner function called');
// }
x(); // now the inner function is called
See this fiddle: http://jsfiddle.net/bBqPY/
Functions in JavaScript can return functions (that can return functions (that can return functions ...)). If you have a function that returns another function then it means that when you call the outer function what you get is the inner function but it is not called yet. You have to call the value that you got as a function to actually run the body of the inner function. So:
x = f();
means - run a function f and store what it returns (which may be a string, a number, an object, an array, or a function) in x. But this:
x = f()();
means - run a function f, expect it to return a function and run that returned function as well (the second parentheses) and store in x what the returned function returned.
The function f here is a higher order function because it returns another function. Functions can also take another functions as arguments. One of the most powerful ideas of functional programming languages in general and JavaScript in particular is that functions are just normal values like arrays or numbers that can be returned and passed around.
You have to first grasp the idea of higher order functions to understand closures and the event system in JavaScript.
2016 Update
Note that currently this:
function outer() {
return function() {
alert('inner function called');
}
}
can be written as:
let outer = () => () => alert('inner function called');
using the ES6 arrow function syntax.
The amazing part about closures is that an inner function (in this case, childFunction) can refer to variables outside of its scope (in this case, variable). parentFunction doesn't return the result of childFunction, but an actual reference to the function!
This means that when you do the following...
var child = parentFunction();
...now, child has a reference to childFunction, and childFunction still has access to any variables it had when the function was created, even if they no longer exist.
In order to have parentFunction call childFunction, you'd need to change your code as follows:
From...
return childFunction;
To:
return childFunction();
Douglas Crockford (Pioneer of JSON, among other things) has a whole article devoted to closures, and scoping in javascript, and it would be well worth it to check out his other articles on javascript.
The point that is being demonstrated is that the function that was returned and assigned to child is still referencing the variable that was declared inside parentFunction instead of the one that was declared outside where child() is being invoked.
The only way to create a variable scope in javascript is in a function body. Normally the variable inside the parentFunction would have been discarded after the function returned.
But because you declared a function inside parentFunction that referenced variable in that scope and passed it out of parentFunction, the variable in the parentFunction is retained via the reference made in the new function.
This protects variable from outside manipulation except by functions that closed around it inside parentFunction.