Functions returning from a method keep a copy of their parent execution context, and this is called closure. But what if the function is inside another function which is inside another function like this:
const a = function() {
const aa = 'aa';
return function() {
const bb = 'bb';
return function() {
return aa;
}
}
}
Now, if I call it like:
a()()();
It'll return "aa" because the nexted-most method seems to have access to its grandparent context. So, do all inner methods keep the execution contexts of all their ancestors in which they're nested, when these inner methods are returned?
So, do all inner methods keep the execution contexts of all their ancestors in which they're nested, when these inner methods are returned?
For almost all practical purposes: Yes.
JS engines do optimise though, so in practise only data that needs to be kept around is kept rather than the whole lexical environment.
For example, given:
const a = () => {
const foo = 1;
const bar = 2;
const b = () => {
console.log(foo);
debugger;
}
}
a()();
Most JS engines will make foo available to b but, because b doesn't use bar, they will discard bar and it won't be available to the debugger.
Closure is just a reference to an environment in which a function is defined.
In the code example (I have given each function a name to make it easy to explain):
const a = function() {
const aa = 'aa';
return function b() {
const bb = 'bb';
return function c() {
return aa;
}
}
}
function c will have a reference to the local scope of function b. Similarly, function b will have a reference to the local scope of function a.
This chain of references is what's known as a scope chain and Javascript will traverse this chain until it finds the identifier aa.
Reference to the environment in which a function is defined is saved in an internal slot which the Ecmascript specification calls the [[Environment]] slot of the function object.
Related
I'm learning about Javascript's module pattern. Below is an example of a "basket" module.
I think I understand that this is an anonymous function that executes, so you can't access variables within it, only what it returns. Why are the variables and functions within this function not deleted / garbage collected after the anonymous function finishes executing? How does JS know to keep them in memory for later use? Is it because we've returned a function which will access them?
var basketModule = (function () {
// privates
var basket = [];
function doSomethingPrivate() {
//...
}
function doSomethingElsePrivate() {
//...
}
// Return an object exposed to the public
return {
// Add items to our basket
addItem: function( values ) {
basket.push(values);
},
// Get the count of items in the basket
getItemCount: function () {
return basket.length;
},
// Public alias to a private function
doSomething: doSomethingPrivate,
// Get the total value of items in the basket
getTotal: function () {
var q = this.getItemCount(),
p = 0;
while (q--) {
p += basket[q].price;
}
return p;
}
};
})();
As long as there is a reference to an object, it will not be garbage collected.
In JavaScript terms, the above code creates a Closure, effectively trapping the outside values inside the inner functions.
Here is a short closure example:
var test = (function() {
var k = {};
return function() {
// This `k` is trapped -- closed over -- from the outside function and will
// survive until we get rid of the function holding it.
alert(typeof k);
}
}());
test();
test = null;
// K is now freed to garbage collect, but no way to reach it to prove that it did.
A longer discussion is available here:
How do JavaScript closures work?
You are referring to closure scopes.
A closure scope is a scope that an inner function has access to, even after the outer function that created the scope has returned!
So, yes, you are correct, the outer 'private' function will not be garbage collected until the inner scope that has access to it is no longer in memory.
Hi still i'm not sure about the exact usage of using closures in javascript.I have idea about closures "A closure is an inner function that has access to the outer (enclosing) function’s variables—scope chain".But i don't know why we are using closures in javascript.
It allows you to succinctly express logic without needing to repeat yourself or supply a large number of parameters and arguments for a callback function.
There is more information available here: javascript closure advantages?
Imagine if instead of
alert("Two plus one equals" + (2+1) );
you'd be forced to declare a variable for every constant you ever use.
var Two = 2;
var One = 1;
var myString = "Two plus one equals";
alert(myAlert + (Two + One) );
You'd go crazy if you had to define a variable for every single constant before you can ever use it.
The access to local variables in case of closures is an advantage, but the primary role - usefulness - is the use of a function as a primary expression, a constant.
Take
function Div1OnClick()
{
Counter.clickCount ++;
}
$('#Div1').click(Div1OnClick);
versus
$('#Div1').click(function(){ Counter.clickCount++; });
You don't create a new function name in the "above" namespace just to use it once. The actual activity is right there where it's used - you don't need to chase it across the code to where it was written. You can use the actual function as a constant instead of first defining and naming it and then calling it by name, and while there are countless caveats, advantages and tricks connected to closures, that's the one property that sells them.
In general, the main use of closures is to create a function that captures the state from it's context. Consider that the function has the captured variables but they are not passed as parameters.
So, you can think of it of a way to create families of functions. For example if you need a series of function that only differ in one value, but you cannot pass that value as a parameter, you can create them with closures.
The Mozilla Developer Network has a good introduction to closures. It shows the following example:
function init() {
var name = "Mozilla";
function displayName() {
alert(name);
}
displayName();
}
init();
In this case the function displayName has captured the variable name. As it stand this example is not very useful, but you can consider the case where you return the function:
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
Here the function makeFunc return the function displayName that has captured the variable name. Now that function can be called outside by assigning it to the variable myFunc.
To continue with this example consider now if the captured variable name were actually a parameter:
function makeFunc(name) {
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc("Mozilla");
myFunc();
Here you can see that makeFunc create a function that shows a message with the text passed as parameter. So it can create a whole family of function that vary only on the value of that variable ("Mozilla" in the example). Using this function we can show the message multiple times.
What is relevant here is that the value that will be shown in the massage has been encapsulated. We are protecting this value in a similar fashion a private field of a class hides a value in other languages.
This allows you to, for example, create a function that counts up:
function makeFunc(value) {
function displayName() {
alert(value);
value++;
}
return displayName;
}
var myFunc = makeFunc(0);
myFunc();
In this case, each time you call the function that is stored in myFunc you will get the next number, first 0, next 1, 2... and so on.
A more advanced example is the "Counter" "class" also from the Mozilla Developer Network. It demonstrates the module pattern:
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
alert(Counter.value()); /* Alerts 0 */
Counter.increment();
Counter.increment();
alert(Counter.value()); /* Alerts 2 */
Counter.decrement();
alert(Counter.value()); /* Alerts 1 */
Here you can see that Counter is an object that has a method increment that advances the privateCounter variable, and the method decrement that decrements it. It is possible to query the value of this variable by calling the method value.
The way this is archived is with an auto-invocation of an anonymous function that creates a hidden scope where the varialbe privateCounter is declared. Now this variable will only be accessible from the functions that capture its value.
Closures are a powerful construct used to implement a lot of additional features in JavaScript. For instance a closure can be used to expose private state as follows:
function getCounter() {
var count = 0;
return function () {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
In the above example when we call getCounter we create a private variable count. Then we return a function which return count incremented. Hence the function we return is a closure in the sense that it closes over the variable count and allows you to access it even after count goes out of scope.
That's a lot of information stuffed in a few lines. Let's break it down?
Okay, so variables have a lifetime just like people do. They are born, they live and they die. The beginning scope marks the birth of a variable and the end of a scope marks the death of a variable.
JavaScript only has function scopes. Hence when you declare a variable inside a function it's hoisted to the beginning of the function (where it's born).
When you try to access a variable which is not declared you get a ReferenceError. However when you try to access a variable which is declared later on you get undefined. This is because declarations in JavaScript are hoisted.
function undeclared_variable() {
alert(x);
}
undeclared_variable();
When you try to access an undeclared variable you get a ReferenceError.
function undefined_variable() {
alert(x);
var x = "Hello World!";
}
undefined_variable();
When you try to access a variable which is declared later in the function you get undefined because only the declaration is hoisted. The definition comes later.
Coming back to scopes a variable dies when it goes out of scope (usually when the function within which the variable is declared ends).
For example the following program will give a ReferenceError because x is not declared in the global scope.
function helloworld() {
var x = "Hello World!";
}
helloworld();
alert(x);
Closures are interesting because they allow you to access a variable even when the function within which variable is declared ends. For example:
function getCounter() {
var count = 0;
return function () {
return ++count;
};
}
var counter = getCounter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
In the above program the variable count is defined in the function getCounter. Hence when a call to getCounter ends the variable count should die as well.
However it doesn't. This is because getCounter returns a function which accesses count. Hence as long as that function (counter) is alive the variable count will stay alive too.
In this case the function which is returned (counter) is called a closure because it closes over the variable count which is called the upvalue of counter.
Uses
Enough with the explanation. Why do we need closures anyway?
As I already mentioned before the main use of closures is to expose private state as is the case with the getCounter function.
Another common use case of closures is partial application. For instance:
function applyRight(func) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
var rest = Array.prototype.slice.call(arguments);
return func.apply(this, rest.concat(args));
};
}
function subtract(a, b) {
return a - b;
}
var decrement = applyRight(subtract, 1);
alert(decrement(1)); // 0
In the above program we had a function called subtract. We used partial application to create another function called decrement from this subtract function.
As you can see the decrement function is actually a closure which closes over the variables func and args.
That's pretty much all you need to know about closures.
It is because of information hiding.
var myModule = (function (){
var privateClass = function (){};
privateClass.prototype = {
help: function (){}
};
var publicClass = function (){
this._helper = new privateClass();
};
publicClass.prototype = {
doSomething: function (){
this._helper.help();
}
};
return {
publicClass: publicClass
};
})();
var instance = new myModule.publicClass();
instance.doSomething();
In javascript you don't have classes with ppp (public, protected, private) properties so you have to use closures to hide the information. On class level that would be very expensive, so the only thing you can do for better code quality to use closure on module level, and use private helper classes in that closure. So closure is for information hiding. It is not cheap, it cost resources (memory, cpu, etc..) so you have to use closures just in the proper places. So never use it on class level for information hiding, because it is too expensive for that.
Another usage to bind methods to instances by using callbacks.
Function.prototype.bind = function (context){
var callback = this;
return function (){
return callback.apply(context, arguments);
};
};
Typical usage of bound function is by asynchronous calls: defer, ajax, event listeners, etc...
var myClass = function (){
this.x = 10;
};
myClass.prototype.displayX = function (){
alert(this.x);
};
var instance = new myClass();
setTimeout(instance.displayX.bind(instance), 1000); //alerts "x" after 1 sec
I'm trying to create a function which returns another function. I want separate information when each of the inner function is run, but this isn't happening. I know that explanation is not great, so I've put together a small example.
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return that;
})(testVal);
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());
This outputs 2, 2. What I would like is 2, 4 to be output. I know this isn't explained perfectly, so if it's not clear what I'm trying to achieve, can someone explain why the variable seems to be shared across the two functions?
Thanks
Like this ?
var testFn = function(testVal) {
var test = testVal
return {
getVal: function() {
return test
}
}
};
var ab = testFn (4)
var ac = testFn (2)
console.log(ab.getVal(),ac.getVal()) //4 //2
The problem in your code is this.getVal() / returning this
because 'this' refers to the global scope / Window
You are glubbering with the global namespace and overwriting Window.getVal() , the moment you are setting b = testFn (2)
This results in overwriting as method getVal too because they both refer to the global Object and always share the same method getVal
Therefore they share the same closure and are outputing 2
console.log("The same: " + (Window.a === Window.b)) // true
console.log("The same: " + (a === b)) // true
you can see that if you change it a little:
var testFn = function(testVal) {
var x = {}
return (function(testVal) {
var test = testVal;
x.getVal = function () {
return test;
}
return x
})(testVal);
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());//4 2
it suddenly works because it results in 2 different Objects returned (btw you don't even need the outer closure)
console.log("The same: " + (a === b)) // false
Here are the JSbins First / Second
I hope you understand this, I'm not good in explaining things
If theres anything left unclear, post a comment and I'll try to update the answer
This question comes down to the context in which functions are invoked in JavaScript.
A function that is invoked within another function is executed in the context of the global scope.
In your example, where you have this code:
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
})(testVal);
}
The inner function is being called on the global scope, so this refers to the global object. In JavaScript a function executed within another function is done so with its scope set to the global scope, not the scope of the function it exists within. This tends to trip developers up a fair bit (or at least, it does me!).
For argument's sake, lets presume this is in a browser, so hence this refers to the window object. This is why you get 2 logged twice, because the second time this runs, this.getVal overwrites the getVal method that was defined when you ran var a = testFn(4);.
JavaScript scopes at function level, so every function has its own scope:
var x = 3;
function foo() {
var x = 2;
console.log(x);
};
console.log(x); //gives us 3
foo(); // logs 2
So what you want to do is run that inner function in the context of the testFn function, not in the global scope. You can run a function with a specific context using the call method. I also recorded a screencast on call and apply which discusses this in greater detail. The basic usage of call is:
function foo() {...}.call(this);
That executes foo in the context of this. So, the first step is to make sure your inner function is called in the right context, the context of the testFn method.
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
}.call(this, testVal);
}
The first parameter to call is the context, and any arguments following that are passed to the function as parameters. So now the inner function is being called in the right scope, it wont add getVal to the global scope, which is a step in the right direction :)
Next though you also need to make sure that every time you call testFn, you do so in a new scope, so you're not overwriting this.getVal when you call testFn for the second time. You can do this using the new keyword. This SO post on the new keyword is well worth reading. When you do var foo = new testFn() you create and execute a new instance of testFN, hereby creating a new scope. This SO question is also relevant.
All you now need to do is change your declaration of a and b to:
var a = new testFn(4);
var b = new testFn(2);
And now console.log(b.getVal(), a.getVal()); will give 2, 4 as desired.
I put a working example on JSBin which should help clear things up. Note how this example defines this.x globally and within the function, and see which ones get logged. Have a play with this and hopefully it might be of use.
The output you get is (2,2) because when you do
var that = this;
what you actually get is the global object (window),
the object that holds all the global methods and variables in your javascript code.
(Note that every variable that is not nested under an object or function is global and
every function that is not nested under an object is global, meaning that functions that are nested under a function are still global)
so, when you set:
var test = testVal;
this.getVal = function() {
return test;
}
you actually set the function "getVal" in the global object, and in the next run you will again set the same function - overriding the first.
To achieve the affect you wanted I would suggest creating and object and returning it in the inner function (as #Glutamat suggested before me):
var testFn = function(testVal) {
return new Object({
getVal: function() {
return testVal;
}
});
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());
In this way, in the outer function we create an object with an inner function called "getVal" that returns the variable passed to the outer function (testVal).
Here's a JSBin if you want to play around with it
(thanks to #Glutamat for introducing this site, I never heard of it and it's really cool :D)
I'm trying to understand javascript scopes, and I want to know if in the following example:
// B can access 'context'
var a = function (context) {
b = function () {
console.log(context);
};
b();
};
a('nicccce'); // works!
// C can't access 'context'
var d = function () {
console.log(context);
};
var c = function (context) {
d();
};
c('oh oh'); // breaks
is there a way of accessing 'context' from the 'd' function?
EDIT:
I know I could pass the argument to the d function and thats obviously the sane thing to do, but I wanted to know if there was another way of doing it, maybe using this.callee as this.callee.arguments[0].
You can either
1) pass context into d as you do for c and a. or
2) put context int the lexical scope of d.
Option 2 sounds complicated, but it isn't. That is exactly what you are doing in the case of b. context is "closed-in" to the execution scope of b because the variable is available on the scope of the caller of b (because it is an argument to a).
No, that's not possible and would result in very ugly/unreadable spaghetti code.
Why can't you pass it as an argument to the function? Another (but also ugly) solution would be declaring the variable in a scope where both functions can access it (i.e. in a parent function or global)
In your example, "context" is a variable scoped to function c() and a() (two different variables in two different scopes with the same name).
Judging from how you named the variable "context", I think .call is what you are looking for?
It is worth saying that scope in javaScript is actually very simple once you get block scope out of your mind. Anything appearing between function { ... } is a scope.
In your case if you pass context as an argument in c it will not break:
// C can access 'context'
var d = function () {
console.log(arguments[0]);
};
var c = function (context) {
d(context);
};
c('oh oh'); // doesn't break
And in d you will be able to access it by using argv/args (can't remember exactly)
So something like args[0] or argv[0]
EDIT:
Changed code with arguments
Define a variable that is in the top scope:
(function(){
var global;
var d = function () {
console.log(global);
};
var a = function (local) {
global = local;
b = function () {
console.log(global);
};
b();
};
}())
I got a piece of code for javascript which I just do not understand:
function dmy(d) {
function pad2(n) {
return (n < 10) ? '0' + n : n;
}
return pad2(d.getUTCDate()) + '/' +
pad2(d.getUTCMonth() + 1) + '/' +
d.getUTCFullYear();
}
function outerFunc(base) {
var punc = "!";
//inner function
function returnString(ext) {
return base + ext + punc;
}
return returnString;
}
How can a function be defined within another function? Can we call pad2() from outside of my() function?
Please put some light on it. Thanks
Functions are another type of variable in JavaScript (with some nuances of course). Creating a function within another function changes the scope of the function in the same way it would change the scope of a variable. This is especially important for use with closures to reduce total global namespace pollution.
The functions defined within another function won't be accessible outside the function unless they have been attached to an object that is accessible outside the function:
function foo(doBar)
{
function bar()
{
console.log( 'bar' );
}
function baz()
{
console.log( 'baz' );
}
window.baz = baz;
if ( doBar ) bar();
}
In this example, the baz function will be available for use after the foo function has been run, as it's overridden window.baz. The bar function will not be available to any context other than scopes contained within the foo function.
as a different example:
function Fizz(qux)
{
this.buzz = function(){
console.log( qux );
};
}
The Fizz function is designed as a constructor so that, when run, it assigns a buzz function to the newly created object. That is, you'd use it like this:
const obj = new Fizz();
obj.buzz();
or more concisely (if you don't need to keep the object after calling buzz):
new Fizz().buzz();
It is called closure.
Basically, the function defined within other function is accessible only within this function. But may be passed as a result and then this result may be called.
It is a very powerful feature. You can see more explanation here:
javascript_closures_for_dummies.html mirror on Archive.org
function x() {}
is equivalent (or very similar) to
var x = function() {}
unless I'm mistaken.
So there is nothing funny going on.
Function-instantiation is allowed inside and outside of functions. Inside those functions, just like variables, the nested functions are local and therefore cannot be obtained from the outside scope.
function foo() {
function bar() {
return 1;
}
return bar();
}
foo manipulates bar within itself. bar cannot be touched from the outer scope unless it is defined in the outer scope.
So this will not work:
function foo() {
function bar() {
return 1;
}
}
bar(); // throws error: bar is not defined
When you declare a function within a function, the inner functions are only available in the scope in which they are declared, or in your case, the pad2 can only be called in the dmy scope.
All the variables existing in dmy are visible in pad2, but it doesn't happen the other way around :D
It's perfectly normal in JavaScript (and many languages) to have functions inside functions.
Take the time to learn the language, don't use it on the basis that it's similar to what you already know. I'd suggest watching Douglas Crockford's series of YUI presentations on JavaScript, with special focus on Act III: Function the Ultimate (link to video download, slides, and transcript)
function foo() {
function bar() {
return 1;
}
}
bar();
Will throw an error.
Since bar is defined inside foo, bar will only be accessible inside foo.
To use bar you need to run it inside foo.
function foo() {
function bar() {
return 1;
}
bar();
}
Nested functions can be the basis for writing a modular group of related functions, kind of halfway to full object-oriented programming (static classes only).
Here is an example of such a group of functions, in this case to convert a value to a JSON string or a JSON string to a value.
Notice how the inner functions are grouped into an Object inside an outer function, and how the Object is then stored into a group name. This is the only name directly visible from outside the group. To reach any contained function from outside, you just write the group name, a period, then the function name. To reach a contained function from inside, you can use the same notation, or 'this', a period, then the function name.
//--------------------------------------------------------------------//
// Module J:
// Convert from and to JSON strings
//--------------------------------------------------------------------//
const J=NewJ();
function NewJ()
{
const mod=
{
From:(str)=>
{
return JSON.parse(str);
}, // From
To:(val)=>
{
return JSON.stringify(val,null,3);
} // To
}; // mod
return mod;
} // NewJ
//--------------------------------------------------------------------//
// End Module J
//--------------------------------------------------------------------//
Here's a test:
console.log(J.To({A:'a'}));
Console output:
{
"A": "a"
}