Javascript supports First Class Functions, in which case we can pass the function as an argument. An anonymous function that is defined inside an argument list of another function, what is the lexical environment (i.e scope) of that anonymous function?
for example:
var m = 2;
(function(p1,p2){
p2(p1);
})(true, function(p1){ // an anonymous function passed as an argument.
m = 3;
if(p1){...}
}); // the end of self-invoked function expression.
The function would have access to the scope where it was defined and include any parent scope (e.g. global/window). If defined inside of another function, it would have access to any variables defined within that function. If passed in as an argument like a callback, it wouldn't have access to variables defined within the function it was passed into because it was defined outside that function and passed in as an argument.
Example:
var a = 1;
(function(callback){ //func1
//access variable in parent scope
console.log('func1', a); //outputs 1
//define a new variable within this function's scope
var b = 2;
//call our callback
callback();
//define and call a function within this function's scope
(function(){ //func3
//access variable in parent scope
console.log('func3', a); //outputs 1
//access variable in parent function scope
console.log('func3', b); //outputs 2
})();
})(function(){ //func2
//access variable in parent scope
console.log('func2', a); //outputs 1
//access variable from invoking function
console.log('func2', b); //outputs undefined
});
This would output something like:
func1 1
func2 1
func2 undefined
func3 1
func3 2
Where all the functions can see variable a because it is in a parent scope to all functions. The argument function can't see variable b because b is defined in another function and the argument function was defined outside and passed in as an argument. And the function defined within the first function can see both a and b.
Calling an IIFE is effectively the same as first assigning the function to a variable, then then calling the function through that variable; as with any other use of anonymous functions, it's just a shortcut that avoids giving a name to the function. So:
(function(p1,p2){
p2(p1);
})(true, function(p1){ // an anonymous function passed as an argument.
m = 3;
if(p1){...}
});
is equivalent to:
var temp = function(p1,p2){
p2(p1);
};
temp(true, function(p1) {
m = 3;
if(p1){...}
});
except for the addition of temp to the outer scope; since this variable doesn't appear anywhere else, it has no effect. The scopes of all other variables are identical in the two scenarios.
When you're unsure what the scopes of a function defined in the arguments list of a call is, notice that
fn(function x(…) { … })
is equivalent to
_temp = function x(…) { … };
fn(_temp)
Arguments are evaluated before the actual call, and they're evaluated in the same scope as the call itself is evaluated in.
Related
I am a little confused regarding closures in this example
function f(param){
var n=function(){ //n is assigned the function that returns param
return param;
};
param++; //increments 1 and n keeps a reference to the param
return n;
}
var inner=f(1);
inner();
I understand the concept of closures, I just dont understand how it works in this example.
Lets see in steps whats happening here:
you call function f with argument 1 and assign the result to variable inner.
When f(1) is called, the scope of f has 2 variables (param and n)
The variable params is the passed argument and n is a function.
So, inside function f -
variable n is initialized to a function, then param is incremented, then n is returned from the function f.
This returned function (n) is assigned to inner.
when inner is called, it returns param - which is in scope of function n due to closure.
Hope the steps were clear.
Now, you're doubt was how n got access to param++. It didn't, param++ was already executed when f(1) was called. All n has is just a reference to the value of param.
In param becomes a local variable to the function which is not same as the argument of the function f. The function f is returning n which is a function
function f(param) {
var n = function() { //n is assigned the function that returns param
return param;
};
param++; // here param become a local variable of the function f
return n;
}
var inner = f(1);
console.log(inner());
Here in this example, the local variable param ends up within a closure of that anonymous function. Here in this case, until the outer function returns, it can change the local execution context which will be used by the anonymous function whenever it gets executed.
Why is it that when I do the following:
var a = 1;
function foo(a) {
a = 2;
}
foo();
console.log(a); // a = 1
But I get a different result for the following:
var a = 1;
function foo() {
a = 2;
}
foo();
console.log(a); // a = 2
In the first example the function foo parameter a is shadowing the global variable a and thus the value of the global variable never changes. The code in the first example is equivalent to this one:
var a = 1;
function foo(x) {
x = 2;
}
In the second example you are referencing the global variable a inside the body of the function foo. Here no variable shadowing occurs so that you get the expected result - a is asigned the value of 2.
JavaScript doesn't really have "parameters on the left/right side." Your first example passes a parameter. Your second example uses a closure.
In programming languages, closures (also lexical closures or function closures) are techniques for implementing lexically scoped name binding in languages with first-class functions. Operationally, a closure is a record storing a function together with an environment: a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created. A closure—unlike a plain function—allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.
In your first example, the variable a inside the function foo is a different variable than a outside of the function. Changing foo's parameter a has no effect on the global variable a that gets passed to console.log.
In your second example, the variable a is not a parameter, but rather a part of the environment that is captured by the function foo. The log shows a modified value of a because the assignment inside foo and the console.log call outside of foo are actually referring to the same variable.
if a is passed in as an argument to that function -- then the value of a within that function is isolated and only accessible within that function. otherwise your a defined outside the function is shared across all functions and objects.
agree with #RomanPerekhrest -- read up.
**UPDATE in reply to comment **
var a = 1;
function foo(a) {
a = 2;
}
foo();
console.log(a); // a = 1
In the code above, the reference to a on lines 2 and 3 are a different variable from the a on lines 1 and 6. In the code from your comment, you are setting a to the value of x within the foo function. That's a bit different from the original question. No?
Can someone explain why in the following function, I am able to pass an argument to a nested function? My understanding is that it has to do something with closures and scope(which I thought I had a decent understanding of), but I can seem to follow how exactly this argument is being passed.
The below function outputs 1,2 respectively. But how is the return statement doThis() getting the argument/parameter for "a"? I cant figure where/how this is accessed/passed.
function doSomething(){
var b = 1;
return function doThis(a){
console.log(b);//1
console.log(a);//2
}
}
var exec = doSomething();
exec(2);
The function doSomething() returns another function so when you execute
var exec = doSomething();
You can think of that exec as containing the following function
function doThis(a){ // <- takes an argument
console.log(1); // comes from the b argument in the outer scope
console.log(a); // not set yet
}
Thus when you call exec(2) you are actually calling doThis() with an argument 2 which becomes the value of a.
This is a slightly simplified version. To expand on that, the doSomething() function is described as closing over doThis() creating a closure. Conversely, the function doThis() is closed over or inside a closure. The closure itself is simply a limited state around the function:
function doSomething(){ // --> defines the closure
var b = 1; // variable only visible within doSomething()
return function doThis(a){ //<--> function has access to everything in doSomething(). Also defines another closure
console.log(b); // --> accesses the OUTER scope
console.log(a); // <-- comes from the INNER scope
} // <-- end INNER scope
} // --> end OUTER scope
When you execute doSomething() the returned result still retains access to the scope within it, this is why doThis() has access to the value b - it's simply reachable for it. It's similar how you can do
var foo = 40;
function bar(value) {
return foo + value;
}
console.log(bar(2));
Only in this instance any other code will have acces to foo as it's a global variable, so if you do foo = 100 in a different function, that will change the output of bar(). A closure prevents the code inside from being reachable from outside the closure.
When you assign var exec = doSomething();, exec is basically writing:
var doSomething = function(a) {
console.log(b);
console.log(a);
}
It became its own function. So passing in 2 like so exec(2) works like any normal function except that it has the variable b available to it because of the closure.
From the Mozilla Doc https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures :
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
Isn't displayName the actual closure as it closes upon the scope of its outer function makeFunc for later use? Mozilla says makeFunc is the closure:
The solution to this puzzle is that myFunc has become a closure. A closure is a special kind of object that combines two things: a function, and the environment in which that function was created.
I remember reading different definitions..
Also Mozilla contradict themselves regarding the following code they say:
function init() {
var name = "Mozilla"; // name is a local variable created by init
function displayName() { // displayName() is the inner function, a closure
alert (name); // displayName() uses variable declared in the parent function
}
displayName();
}
init();
init() creates a local variable name and then a function called displayName() displayName() is the inner function (a closure) — it is defined inside init(), and only available within the body of that function.
So in summary they say both the inner function and the outer function have become a closure..
SORRY QUESTION CLSOED. I misread 'myFunc' as 'makeFunc' -_-
I think you misread the docs - myFunc is the closure, bnot makeFunc, as you thought it was.:
init() creates a local variable name and then a function called displayName(). displayName() is the inner function (a closure) — it is defined inside init(), and only available within the body of that function . Unlike init(), displayName() has no local variables of its own, and instead reuses the variable name declared in the parent function.
Just replace init with makeFunc and apply the quote above to your code. displayName is what is returned, and thus exposed. It's a function object with access to the var name.
So yes, displayName is a closure, and it's a closure that is created and returned by makeFunc.
When you assign this returned closure to a variable, then that variable is that closure. In your case myFunc is assigned the return value of createFunc, meanting it is assigned an instance of a function, called displayName inside itself, that has access to a var name.
The next time createFunc is invoked, a new name var will be created, and a new displayName function is created. If you assign that to another var, then you have 2 closures that, even though they use the same variable names internally, and they were both returned by the same function, are 2 separate closures.
In JS, functions are first-class objects (meaning they can be passed around and assigned like any other value). This means that:
var foo = function (bar) //assign function to variable foo
{
return function()//this function will return a function
{
bar();//that invokes bar, an argument passed to the outer function
alert('bar was invoked');
};
}
var closure = foo(function(){ alert('test');});//pass function to foo
//returns the inner function, that invokes the function we just passed:
closure();//will alert "test", and then "bar was invoked"
var closure2 = foo(function(){ alert('a new closure');});
closure2();//alerts "a new closure" and "bar was invoked"
closure();// still alerts the same
From Wikipedia:
In programming languages, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment
So displayName is the function and makeFunc is the source of the referencing environment, and together they make the closure.
let's suppose we have a javascript function and we want to check if the second parameter is undefined, in that case we want to assign it a value such as
function myFunc(a,b){
if(typeof b==="undefined" ){
b=0;
}
//do stuff
}
Does the variable b in the if block still refer to the function's parameter or a global variable named b is created?
Cheers
Yes, b gets resolved in the lexicalEnvironment (ES5) respectively Activation Object (ES3). It will always get resolved locally, even if a global variable b exists aswell by accessing the pure name.
You would need to explicitly call window.b respectively global.b (node) to access that global variable with the same name.
It refers to the function's parameter. You can test yourself like so:
var b = 45;
function myFunc(a,b){
if(typeof b==="undefined" ){
b=0;
}
alert( b ); //It will output 0
//do stuff
}
myFunc('');
The answers by #Andre and #Nelson are both correct, but just for clarity's sake:
var c = 123;
var func = (function(a)//a === 1234
{
var b = c;//local b === global c
return function(a,c)
{
console.log(c === b);//false, unless second argument was 123
console.log(a === 1234);//false, unless first arg was 1234
console.log('a masks the a of the outer scope');
};
})(1234);
JS will first scan the scope of the called function, for any vars used, if it doesn't find them there, it moves on to the outer scope. This can be another function, or, eventually, the global scope. In this example, the inner (returned) function will not be able to access the value of a as defined in the outer function. It's GC'ed when that outer function returned, because it's not being referenced anywhere.
code:
function myFunc(a,b){
if(typeof b==="undefined" ){
b=0;
}
console.log('b from myFunc:'+b)
}
myFunc(5);
console.log('global:'+b)
output:
b from myFunc:0
b is not defined
Javascript first looks in the local scope for either a local variable or a named function argument. If it finds the symbol there, then that variable is the one that is used.
Only if a matching local symbol is not found is a global symbol used.
Thus, in your example, you will be setting the value of b the function argument.
Once you've defined a local symbol in either a local variable or a named function argument, you can no longer use that name by itself to access a global variable of the same name. If you specifically want to address the global variable, you can do so by prefixing it with window. as in window.b. This specifically targets the global scope so the local scope is not used.
The variable stays on the function if;
the variable is declared inside the function using var or without it
the variable is declared with this as it's parent node the function, example below
function foo(){
this.bar = 'hello';
}
the variable becomes available in the global scope when
the variable is declared outside any function using var or without it
the variable is declared as it's parent node is window example below
window.bar ='i am global'
YOU NEED DEFINE VARIABLE GLOBALLY :
In the below code t2 is undefined.
<script>
var t1="";
var t2;
function check(t1,t2){
if (t1===undefined)
{
alert("t1 is undefined");
}
if (t2===undefined)
{
alert("t2 is undefined");
}
}
</script>
REF :
http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_undefined