I believed at first look both self invoking function is same only difference between them is in first one I am passing callback function and then executing by arguments object while in second doing same thing by making function self invoking. Now come to points of accessing parent variable in first one example name is "undefined" while in second one example it's accessible and giving output "Nishant" I am not able to figure out how It's working!!
(function(){
var name = "Nishant";
arguments[0]();
})(function(){console.log(name);});
Output: (an empty string)
(function(){
var name = "Nishant";
(function(){console.log(name);})()
})();
Output: Nishant
I am not able to figure out how It's working!!
JavaScript has lexical scope. That means the scope is determined by where the functions are defined inside the source code (unlike dynamic scope, where the scope is determined when the functions are called at runtime).
Lets add some names to your functions so we can reference them more easily:
(function foo(){
var name = "Nishant";
arguments[0]();
})(function bar(){console.log(name);});
In this case bar is defined outside of foo and hence cannot have access to the variable defined inside of foo. In fact, at the moment bar is created, the variable name inside foo doesn't even exist yet, since foo hasn't been executed yet.
Maybe it's easier to see when you do not inline the definition:
function bar(){console.log(name);}
(function foo(){
var name = "Nishant";
arguments[0]();
})(bar);
This might look more familiar, and I bet you wouldn't expect that name inside bar has anything to do with name inside foo, right?
In the other case,
(function foo(){
var name = "Nishant";
(function bar(){console.log(name);})()
})();
you defined bar inside of foo. name is also inside foo and hence bar has access to that variable (lexical scope + closure).
the "name" in the first version refers the global window.name property*, and in the second example to the private var name through the closure. The window.name property is optional and defaults to an empty string.
If this property wouldn't happen to exist your first example would throw a reference error.
The closure is created at the scope a function was declared, not at the point it got called and in the first example the function was declared inside the global scope, in the second inside the wrapper function scope.
window.name = "NoClosure";
(function(){
var name = "Closure";
arguments[0]();
})(function(){console.log(name);}); //>"NoClosure"
window.name = "NoClosure";
(function(){
var name = "Closure";
(function(){console.log(name);})(); //>"Closure"
})();
If you inspect the of the callback with console.dir(), you can see that it has no closure, here a snippet if you want to test it yourself.
(function wrapper(){
var isPrivate = "A closure could see me";
console.dir(arguments[0]);
})(function callback(){});
Here is another experimental setup with 2 closures showing that function declared inside a call to a function are capable of getting a closure, but it will always be the closure of the scope of the function passing it, it can not access the scope of the function it was passed to as an argument and that later calls it as a callback.
(function outerScope(){
var outerVar = "in outer scope";
(function innerScope(cb){
var innerVar = "in inner scope";
cb();
})(function callback(){
console.log(
"outer:"+ typeof outerVar,
"inner:"+ typeof innerVar);
console.dir(arguments.callee);
})
})()
*source https://developer.mozilla.org/en-US/docs/Web/API/Window.name
Related
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?
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.
JavaScript normally follows the function scope i.e. variables are accessible only within the function in which they are declared.
One of the ways to break this convention and make the variable accessible outside the function scope is to use the global window object
e.g.
window.myVar = 123;
My question is are there any other ways in JavaScript/jQuery to make the variable accessible outside the function scope?
Not with variable declarations, no. You can obviously declare a variable in an outer scope so that it's accessible to all descendant scopes:
var a; // Available globally
function example() {
a = "hello"; // References a in outer scope
}
If you're not in strict mode you can simply remove the var keyword. This is equivalent to your example:
// a has not been declared in an ancestor scope
function example() {
a = "hello"; // a is now a property of the global object
}
But this is very bad practice. It will throw a reference error if the function runs in strict mode:
function example() {
"use strict";
a = "hello"; // ReferenceError: a is not defined
}
As you wrote, variables are only visible inside the function in which they were defined (unless they are global).
What you can do is assign variables to the function object itself:
function foo() {
foo.myVar = 42;
}
console.log(foo.myVar); // outputs "undefined"
foo();
console.log(foo.myVar); // outputs "42"
But I would advise against it. You should really have a very good reason to do something like this.
You can define them as part of a global object, then add variables later
// Define your global object
var myObj = {};
// Add property (variable) to it
myObj.myVar = 'Hello world';
// Add method to it
myObj.myFunctions = function() {
// Do cool stuff
};
See the link below:
Variable declaration
Also, you can declare it without the var keyword. However, this may not be a good practice as it pollutes the global namespace. (Make sure strict mode is not on).
Edit:
I didn't see the other comments before posting. #JamesAllardice answer is also good.
From Javascript-Garden:
Foo.method = function() {
function test() {
//this is set to the global object
}
test();
}
In order to gain access to Foo from within test, it is necessary to create a local variable inside of method that refers to Foo:
Foo.method = function() {
var that = this;
function test(){
//Use that instead of this here
}
test();
}
Could anyone explain this? As far as I understood, this refers to the global object if it's called in the global scope. But here it's called inside of a function, which is inside a method (first example). Why exactly does it refer to the global object, while the second example doesn't?
As far as I understood, this refers to the global object if it's called in the global scope.
No. this will refer to the default object if the function is called without explicit context. The scope is irrelevant. (In strict mode it will refer to undefined instead).
Why exactly does it refer to the global object
We can't tell what it refers to. The value of this is determined by how the function is called, not how it is defined.
Now you have updated the example, we can see that it is called without context, so this (in the inner function) will be the default object, which in a web browser is window (it would be undefined in strict mode).
while the second example doesn't?
In the second example, the inner function doesn't use this (which will have the same value as the previous example).
The second example uses that instead. that is defined in the scope of the outer function and is set to whatever the value of this is when that function is called.
Assuming that function is called as Foo.method() then (outer) this (and hence that) will be Foo because that is the context on which method was called.
this in a function isn't set when you define the function. It's only dynamically defined to the receiver of the function call.
If you call foo.test(), this in test will be foo.
But if you do
var f = foo.test;
f();
then this in f (which is foo.test) will be the external object (window if you're executing it at the root level).
It would be the same with
foo.test.call(window);
The second example uses a closure to place the outer functions variables on the scope chain of the inner function.
Foo.method = function() {
var that = this;
function test(){
//This function has access to the outer variables scope chain.
}
}
I've reading scope chain in Javascript but it didn't make any sense to me, could any one tell me what is scope chain and how it works with a graphic or something even an idiot can understand. I googled it but I didn't find something comprehensible :(
To understand the scope chain you must know how closures work.
A closure is formed when you nest functions, inner functions can refer to the variables present in their outer enclosing functions even after their parent functions have already executed.
JavaScript resolves identifiers within a particular context by traversing up the scope chain, moving from locally to globally.
Consider this example with three nested functions:
var currentScope = 0; // global scope
(function () {
var currentScope = 1, one = 'scope1';
alert(currentScope);
(function () {
var currentScope = 2, two = 'scope2';
alert(currentScope);
(function () {
var currentScope = 3, three = 'scope3';
alert(currentScope);
alert(one + two + three); // climb up the scope chain to get one and two
}());
}());
}());
Recommended reads:
JavaScript Closures
Closures
Any function call in ECMAScript ( core language that JS is based on ) produces a separate execution context, which run individually from one another. Inside of each execution context, this refers to the object in question, defaulting to whatever the function is attached to.
function foo() {
alert(this===window)
}
Would alert true, because the window is the object which owns the 'foo' method. Any variables defined in a function become accessed through that function's unique scope chain, environment.
function world() {
var name = 'global';
alert(name)
}
would alert 'global' obviously.
function world() {
var name = 'global';
(function() {
var name = 'country';
alert(name)
})();
alert(name)
}
In the latest example, when the first alert is invoked, Javascript determines that in the scope chain of the inner function that the identifier name is defined, so it doesn't have to look up the scope chain to grab it.
In the second alert invocation, name is also defined in the same context and alerts 'global';
function world() {
var name = 'global';
(function() { alert(name) })();
}
In this example, the name identifier is not defined in the same context and thus it has to travel up the scope chain to the outer function where name is defined, and it alerts global.
Reference:
http://www.digital-web.com/articles/scope_in_javascript/
http://www.jibbering.com/faq/faq_notes/closures.html
I know it's an old post but it is still helpful for developers. I wanted to do it little different way as it would be more friendly for beginners to understand scope chaining. Here is my modified version of code:
var currentScope = 0; // global scope
function a () {
var currentScope = 1, one = 'scope1';
alert(currentScope);
function b () {
var currentScope = 2, two = 'scope2';
alert(currentScope);
function c () {
var currentScope = 3, three = 'scope3';
alert(currentScope);
alert(one + two + three); // climb up the scope chain to get one and two
}
c();
}
b();
}
a();
This is about closure. You may use variables outer from scope in the inner scope:
function get_inner_scope () {
var outer = 'Outer variable value';
return function () {
alert(outer);
}
}
f = get_inner_scope();
f(); // alerts Outer variable value
More deatailed info with other samples by first google's link:
http://blogs.msdn.com/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx
Summary:
The scope chain is used to resolve the value of variable names in javascript. Without a scope chain the Javascript engine wouldn't know which value to pick for a certain variable name if there are multiple defined at different scopes. Scope chain in javascript is lexically defined, which means that we can see what the scope chain will be by looking at the code.
At the top of the scope chain is the global scope, which is the window object in the browser (global in NodeJS). Besides from the global scope, functions have their own scoping of variables. The scope chain can be determined by looking at where functions are defined.
When resolving a variable, inner functions first look at their own scope. If the variable cannot be found in its own scope it will climb up the scope chain and looks for the variable name in the environment where the function was defined. This look like this:
So in our image example when innerFoo uses the variable bar it first tries to find it within the scope of the innerFoo (code within function body). Then when it doesn't find it here it climbs up the scope chain to foo. In foo there is also no variable which is named bar. Therefore, it will climb up the scope chain and now look in the global scope. In the global scope is a variable named bar with a value of 10 to which bar will be resolved.
Example:
let foo = 1;
let bar = 1;
function test (bar) {
return function innerTestFunc () {
let foo = 10;
console.log(foo, bar);
}
}
const innerTestFunc1 = test(5);
const innerTestFunc2 = test(20);
innerTestFunc1(); // logs 10, 5
innerTestFunc2(); // logs 10, 20
In the above example we have a function which returns a function. We first store this function in the variables innerTestFunc1 and innerTestFunc2. This creates a closure which is basically a snapshot of the scope chain of the outer environment.
Then when the functions are executed the function requires a value for both the variables foo and bar. The value of foo can be resolved at the level of the innerTestFunc and is 10 for both. 10 is already found in innerFoo, so no need to climb the scope chain for foo.
In the case of the bar variable the function cannot find it in the innerFoo. Therefore, it will climb up the scope chain. It first encounters the variable bar in the function test, therefore it will resolve value of bar to whatever the value is in the test function (5, 20 in our example).
Scope chain in Javascript explained in layman terms
Alex is a happy guy,One fine day,walking down the road with his monthly salary in hand gets mugged.
Later he realizes that tomorrow is the last day to pay for his daughters tuition of 1000$.
He runs home,finds his savings of 400$,worries about the rest(600$).The immediate thought that flashes,is to borrow some from his father Mathew.
Mathew,the poor carpenter,devoid from any money sells his inherited bracelet for 300$ and lends it to his son Alex.
Alex having a good reputation in the society,gets the remaining 300$ from a local bank immediately and pays his daughter tuition on time.
Coming back to Scope chain in Javascript:
Alex-A function in javascript
Mathew-The immediate function,Alex is nested in.
Mathews parents-The immediate function Mathew is nested in.
Bank-Global variables.
function Bank() {
loan=300;
Mathew();
function Mathew() {
mathew=300;
Alex();
function Alex() {
savings:400;
alert('I need some money');
}
}
}
Bank();
Scope chain of Alex at this point looks like:
[savings:400]+[mathew:300]+[loan:300];