Still feel my understanding of Javascript closure is a little woolly at times and I would like to know if the code below represents closure in action...
function StateManager () {
var self = this;
this.state = null;
$(document).on("internal_StateManager_getState", function () {
return self.state;
});
$(document).on("internal_StateManager_setState", function (e, p) {
if ( p && p.state ) {
self.state = p.state
}
return self.state;
});
};
new StateManager();
alert( $(document).triggerHandler("internal_StateManager_setState", { "state": 88 }) );
Is it accurate to say that this demonstrates closure because the state and self variables are accessable via the events? Thanks for any input!
In the code in the question, the StateManager function does not create a closure, as it doesn't reference "free" variables from outside it's lexical scope.
However the jQuery callbacks are in fact closures, as they do reference the self variable which is defined outside the lexical scope of the callback functions.
A closure is, from MDN
Closures are functions that refer to independent (free) variables.
In other words, the function defined in the closure 'remembers' the environment in which it was created.
A simple example would be something like
function something() {
var test = "Hello Kitty"; // "test" is a local variable created in this scope
function otherFunc() { // this is an inner function, a closure
alert( test ); // uses variable declared in the parent function
}
}
That's about as simple as closure gets, it's just a function inside another function that uses variables outside it's lexical scope.
Another familiar example would be
$(document).ready(function() { // creates outer scope
var data = 'important stuff';
$('.elems').on('click', function() { // this is a closure
$(this).text( data ); // uses variable outside it's scope
});
});
Related
Im reading "Eloquent Javascript" book and I'm in the chapter "The secret life of objects".
And the author says:
"since each function has it's own bindings, whose value depends on
they way it is called, you cannot refer to the this of the wrapping
scope in a regular function defined with the function keyword.
i did not understand what does he mean by "wrapping scope", can you please explain and provide a simple example?
Wrapping scope of your function would be the scope where the function is defined.
e.g.
function outer() {
var outerThis = this;
return function inner() {
console.log(outerThis, this);
}
}
Here, inner function has wrapping scope = scope of outer. And, the inner function doesn't have access to the outer's this which is why we need to store it in a variable outerThis if we want to use it.
var innerFunction = outer.call({});
innerFunction();
If you do above on chrome console, This will print:
{}, // Caller of outer() (it was bound)
Window // Caller of inner()
Here is an example of how the use of "function" keyword will produce a function that does not have the same meaning to "this" as the containing scope has. You can overcome this by using an arrow function.
See also: https://medium.com/better-programming/difference-between-regular-functions-and-arrow-functions-f65639aba256
const container = {
name: "Bob",
sayName: function() {
console.log('say name root:', this.name);
const nestedWithFunctionKeyword = function() {
// Notice here that introducing "function" ruins the "this" reference. It no longer is referring to "container".
console.log('say name function:', this.name);
};
nestedWithFunctionKeyword();
// But we can re-bind "this" if we want.
nestedWithFunctionKeyword.call(this);
const nestedWithArrowSyntax = () => {
console.log('say name with arrow:', this.name);
};
nestedWithArrowSyntax();
},
};
container.sayName();
console.log('-----------------');
// Now lets look how how "the way you call the function" matters. Here we do not call the function within the context of "container" anymore, so the results change.
const sayNameRef = container.sayName;
sayNameRef();
this keyword refers to the object it belongs to, for example:
function diner(order) {
this.order = order;
this.table = 'TABLE 1';
this.eatHere = eatHere
this.goOutside = goOutside
function eatHere() {
// adding () instead of a function
// will use the scope of the object it self
setTimeout(() => {
console.log(`EAT HERE: eating ${this.order} at ${this.table}`);
}, 200);
}
function goOutside() {
// adding a new function scope inside the function
// will go outside the current object's scope
setTimeout(function () {
console.log(`EAT OUTSIDE: eating ${this.order} at ${this.table}`);
}, 200);
}
}
let obj = new diner("soup");
obj.eatHere(); // this order will be defined
obj.goOutside(); // this order will be undefined
Let us consider the workable code:
var storage = {};
(function() {
function internalMethod1() { ...; return; }
function internalMethod2() { ...; return; }
storage.storedMethod = internalMethod1;
})();
storage.storedMethod();
Is there any way to call internalMethod2, if it is not called in internalMethod1? In other words, can I access an anonymous closure from outside, if I have access only to one of its functions?
can I access an anonymous closure from outside?
No. Scopes are private in JS, and there's absolutely no way to access them from the outside (unless you use the engine's implementation-specific debugging API…).
Variables (including functions) are only available in the same scope and its children. If you want to access their values outside of the scope, you're at the mercy of the function to expose them in some way (return, assign to global storage variable etc).
No, you cannot access a private, unreferenced scope after it has been executed. You would need to create another closure to create a reference to whatever private method you wanted to expose.
var storage = {};
(function() {
function internalMethod1() {
return {
internalPublic1: internalMethod2
};
}
function internalMethod2() {
console.log('hi');
}
storage.storedMethod = internalMethod1;
})();
var a = storage.storedMethod();
a.internalPublic1(); //'hi'
Try defining IIFE as variable , return reference to internalMethod2 from IIFE
var storage = {};
var method2 = (function() {
function internalMethod1() { console.log(1) };
function internalMethod2() { console.log(2) };
storage.storedMethod = internalMethod1;
return internalMethod2
})();
storage.storedMethod();
method2();
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 thought one of the point of functions in javascript was to provide scope. Things defined in a function were only available inside the function.
function cat(name) {
talk = function() {
alert(" say meeow!" )
}
}
talk()
I would expect the above code to fall over because talk should not be visible. But it is, why?
It is because you didn't declare it with a var keyword.
If you don't use the var keyword, it will be in the global scope. If you do use var, it will be in the function scope:
function cat(name) {
//anonymous function assigned to the local variable talk
var talk = function() {
alert(" say meeow!" )
};
}
You can declare named functions without the var keyword, and they will still be in the local scope:
function cat(name) {
//local talk function
function talk() {
alert(" say meeow!" )
};
}
You haven't actually defined the variable in any scope. So it default to global scope.
function cat(name) {
var talk = function() { // <-- added var
alert(" say meeow!" )
}
}
talk() // fail
JavaScript allows you to use variables without defining them, this makes the programming language easier to learn and more flexible. I wouldn't recommend you make use of this feature though. Always define your variables.
inside of a function, you have to declare variables with "var" or they are declared globally. so you would do:
function cat(name) {
var talk = function() {
alert(" say meeow!" )
}
}
talk() // error: undefined