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.
Related
I understand that every function in JavaScript is a first-class object and it has an internal property [[scope]] which hosts the binding records of the function's free variables. However, there are two special cases.
Is the function created by Function constructor also a closure? The function object created by Function constructor is special, because its [[scope]] may not refer to the lexical environments of its outer functions, but only the global context. For example,
var a = 1;
var fn = (function outer() {
var a = 2;
var inner = new Function('alert(a); ');
return inner;
})();
fn(); // will alert 1, not 2.
This is unintuitive. Is this also called closure?
If an inner function doesn't have any free variables, can we say a closure is formed when the inner function is created? For example,
// This is a useless case only for academic study
var fn = (function outer() {
var localVar1 = 1,
localVar2 = 2;
return function() {};
})();
In this case, fn refers to an empty function object which was created as an inner function. It has no free variables. In this case can we say a closure is formed?
Is the function created by Function constructor also a closure?
Yes, it closes over the global scope. That might be unintuitive because all other JavaScript closures close over their lexical scope, but it still matches our definition of a closure. In your example, a is a free variable, and resolves to the a in an other scope when the inner/fn function is called somewhere.
If an inner function doesn't have any free variables, can we still call it a closure?
Depends on whom you ask. Some say Yes, others call them "uninteresting closures", personally I say No because they don't reference an outer scope.
Note: Functions created with the Function constructor do not create
closures to their creation contexts; they always are created in the
global scope. When running them, they will only be able to access
their own local variables and global ones, not the ones from the scope
in which the Function constructor was called. This is different from
using eval with code for a function expression.
from https://developer.mozilla.org
I have read over some rules to determine what the value of this is in different scenarios in Javascript. All was well till the example below threw me off.
function Person(name){
this.name = name; //this is the object when function used as constructor (as expected)
this.changeName = someFunction(); // produces error
function someFunction(){
this.nickName = this.name+"by"; //this is now the global object and not the instance, thus the name property does not exist.
}
}
var a = new Person ('bob'); //error due to the function in changeName property.
From what I understood, the this variable takes up the value of the invoking object when called through dot notation or takes up the value of the newly constructed function when used with the new key word.
Can someone explain why the this statement in the function above is the global objet and not the newly instantiated object?
Can someone explain why the this statement in the function above is the global objet and not the newly instantiated object?
Because when you call a(n unbound) function as func(), this will refer to the global object (or undefined if the function is in strict mode).
Every function (except arrow functions) has its own this value. So the fact that you are calling Person as new Person() and that this inside Person refers to a new object, doesn't have any impact on the this value in someFunction. It only matters how you can someFunction.
You could call someFunction and explicitly set its this value via .call:
this.changeName = someFunction.call(this);
See also: How to access the correct `this` inside a callback?
The this within someFunction() will reference a global object, because it's inside a function call. See a fuller, much more complete explanation at How does "this" keyword work within a function?
If you wish to solve the issue, alias this inside the parent.
function Person(name){
var self = this; // Store a reference to the current instance
self.name = name;
self.changeName = someFunction(); // Odd that you'd capture the return value of a setter, ...
function someFunction(){
self.nickName = self.name+"by"; //self references the instance, creating the property.
}
}
I understand that every function in JavaScript is a first-class object and it has an internal property [[scope]] which hosts the binding records of the function's free variables. However, there are two special cases.
Is the function created by Function constructor also a closure? The function object created by Function constructor is special, because its [[scope]] may not refer to the lexical environments of its outer functions, but only the global context. For example,
var a = 1;
var fn = (function outer() {
var a = 2;
var inner = new Function('alert(a); ');
return inner;
})();
fn(); // will alert 1, not 2.
This is unintuitive. Is this also called closure?
If an inner function doesn't have any free variables, can we say a closure is formed when the inner function is created? For example,
// This is a useless case only for academic study
var fn = (function outer() {
var localVar1 = 1,
localVar2 = 2;
return function() {};
})();
In this case, fn refers to an empty function object which was created as an inner function. It has no free variables. In this case can we say a closure is formed?
Is the function created by Function constructor also a closure?
Yes, it closes over the global scope. That might be unintuitive because all other JavaScript closures close over their lexical scope, but it still matches our definition of a closure. In your example, a is a free variable, and resolves to the a in an other scope when the inner/fn function is called somewhere.
If an inner function doesn't have any free variables, can we still call it a closure?
Depends on whom you ask. Some say Yes, others call them "uninteresting closures", personally I say No because they don't reference an outer scope.
Note: Functions created with the Function constructor do not create
closures to their creation contexts; they always are created in the
global scope. When running them, they will only be able to access
their own local variables and global ones, not the ones from the scope
in which the Function constructor was called. This is different from
using eval with code for a function expression.
from https://developer.mozilla.org
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
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.
}
}