Let's say I declare a function and use it as a handler for an event on an object.
Let's say that it needs to access a variable who's value will change before the event is called.
How do I provide to the function the value of the variable the moment the function is declared?
For example:
var I_Like_to_Change_Frequently = "...";
some_DOM_object.addEventListener( "some_arbitrary_event_to_fire_later", function I_Need_the_Current_Value(){
alert( "at the time I was defined, 'I_Like_to_Change_Frequently' was " + I_Like_to_Change_Frequently)
})
var I_Like_to_Change_Frequently = undefined //doesn't really matter. The point is it changes
EDIT: This codeblock is repeated multiple times in a for loop where some_DOM_object is different each iteration. Every iteration I_Like_to_Change_Frequently changes as well.
A couple options:
1) Move your code into a function. The function parameter will be a new binding, and thus will be "locked in" to that value
function createListener(domObject, val) {
domObject.addEventListener("some_arbitrary_event_to_fire_later", function () {
alert("at the time i was defined, I_Like_to_Change_Frequently was " + val;
});
}
var I_Like_to_Change_Frequently = "...";
createListener(some_DOM_object, I_Like_to_Change_Frequently);
var I_Like_to_Change_Frequently = undefined
2) Do it inline with an IIFE
var I_Like_to_Change_Frequently = "...";
(function (val) {
some_DOM_object.addEventListener( "some_arbitrary_event_to_fire_later",
function (){
alert( "at the time I was defined, 'I_Like_to_Change_Frequently' was " + val)
})
})(I_Like_to_Change_Frequently);
var I_Like_to_Change_Frequently = undefined
Using Function.prototype.bind():
You can also make use of the javascript bind() function to define the scope of the function.
This way, the variable value at the time of creation of the function can be retained.
some_DOM_object.addEventListener( "some_arbitrary_event_to_fire_later", (function I_Need_the_Current_Value(){
alert( "at the time I was defined, 'I_Like_to_Change_Frequently' was " + this.variableAtTheTimeOfCreation)
}).bind({variableAtTheTimeOfCreation: I_Like_to_Change_Frequently}));
Breakdown:
In this example, we bind the function to a scope object {variableAtTheTimeOfCreation: I_Like_to_Change_Frequently}.
When the handler executes, it's this will be the scope object we defined and bound to it (which was at creation).
More on Function.prototype.bind() on MDN
Related
I'm trying to get a solid understanding of closures, and I'm struggling with the mechanics of it. I've looked on w3schools (https://www.w3schools.com/js/js_function_closures.asp) and MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) and a few other places. I understand what a closure is and how to make it work but I don't understand why subsequent calls after the first call to the outer function just seem to go straight to the inner one instead.
Here is my code - a simple, working closure:
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})();
function getAdd() {
document.getElementById("test").innerHTML = add();
}
I have two questions that probably both have the same answer: Why does a not get reset every time I call add()? And why does the alert not pop up except for on the first time?
I attached getAdd() to a button, and it works great, but it but doesn't pop up with the alert past the first time. Why does it do this?
Edit: I also found the first answer to this question (Why Don't Variables Reset in a Closure (Javascript)) really helpful.
add is a reference to addInner, not the anonymous "outer" function, since the "outer" function returns addInner. Then, you call that anonymous function once - that last set of ()- and store the resulting function, with its own private 'a', in add.
Imagine that the outer function was a named function called constructAdder, and you called
var add = constructAdder();
var add2 = constructAdder();
That's basically what you've done, but with an anonymous function, if that makes it any clearer. You have an outer function that constructs an inner function that can count, due to the magic of closures.
Those questions do both have the same answer. And it's fairly simple. This statement:
var val = (function() {
return 42
}())
sets val to 42. Not a function. This is called an IIFE, or immediately-invoked function expression. We are declaring a function and calling it immediately. We never save that function. We just use it once to get the value it returns:
val // 42
Contrast that to:
var val = function() {
return 42
}
In this case we set val to a function that, when called, returns 42.
val() // 42
val() // 42
We can get pretty crazy with IIFEs:
var val = (function() {
return (function() {
return (function() {
return 42
}())
}())
}())
The value returned by that mess is still 42.
val // 42
All those functions are declared once, used once, and thrown away. But IIFEs are capable of so much more:
var add = (function() {
var counter = 0
return function() {
return counter++
}
}())
We're now using the IIFE to create a private variable! counter cannot be accessed outside the scope of the IIFE. It's safe. But the inner function can access and modify it. It's a fully encapsulated, stateful function!
add() // 0
add() // 1
counter // Uncaught ReferenceError: counter is not defined
This is what your code is doing:
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})();
It is encapsulating the a variable so that it cannot be accessed outside the scope of the IIFE. The addInner function, however, does have access to a and can modify it at will.
The alert() is only called once because that IIFE is only called once, then thrown away. Note that the function itself is the only thing thrown away. Since addInner maintains a reference to the scope (closure) created by the IIFE, that scope is safe from garbage collection.
In fact, that's a helpful way to think about IIFEs:
var val = function() {}
creates a function and
val()
creates a closure (the context that the function's body runs in). IIFEs are used when we don't care about the function, we just want the closure it creates.
Hope this helps. Have fun out there!
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})(); <-- This
The () at the end means that add is added forever, and if you look at the line above, then it says return addInner. This means that add() is actually addInner(), the good thing with this is that addInner has access to a. Actually writing the function like this is more proper.
var add = (function () {
this.a = 0;
alert('hi');
var addInner = function(){
this.a += 1;
return this.a;
}.bind(this);
return addInner;
})();
Because now you would think that add.a would make a available because it is written as this.a, but since addInner is returned, then it is not available.
You should focus on the
(function(){
// impl
})()
block.
It is called an Immediately Invoked Function Expression or IIFE.MDN reference
So when the code executes to line 1, it first evaluate the right side and the IIFE returns a closure which was then assigned to the variable add. Meanwhile, an alert was invoked in the IIFE. Understanding the IIFE can help you solve the problems.
In my opinion , the key is IIFE, after the code below is executed at the first time,
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})();
(Look out ! There is no add() in the code above because IIFE will be Invoked Immediately and the return addInner finished the initialization of variable add )
the function add has been changed to :
add = function addInner() {
a += 1;
return a;
}
Of course, the alert() only executed one time because the add has been changed at the begining.
Why does a not get reset every time I call add()?
And why does the alert not pop up except for on the first time?
that is the answer of your question.
variable a didn't destroy because the function add still have a reference, and this is about the closure.
Here I have copied code snippet from MDN : https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();
// after 1 second, triggers the 'declare' method
The most confusing part is : window.setTimeout(this.declare.bind(this), 1000);
I understand how this works and this inside settimeout is always bound to global object.I know there can be var self or var that inside bloom function.
There are two this in that line but which this refers to what and how that works is totally confusing.
How works?
First of all read this article, which offers a very nice explanation about how this works.
.bind(this, args) just helps you to pass your this context inside your function (because inside it in your example by default this is undefined or refers to window).
Also bind is a nice alternative to this:
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
var self = this;
window.setTimeout(self.declare, 1000);
};
And as the last point in es6 you can do it in this way:
window.setTimeout(() => {
//do some stuff
}, 1000);
instead of
window.setTimeout(function () {
//do some stuff
}.bind(this), 1000);
this allow you to not think about this.
MSDN defines Function.prototype.bind() as,
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
By using .bind(this) we are passing this to the function declare
See this snippet.
function LateBloomer() {
console.log(this.constructor);
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.undefinedbloom = function() {
window.setTimeout(this.declare, 1000);
};
LateBloomer.prototype.declare = function() {
console.log(this.constructor);
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();
flower.undefinedbloom();
In the function undefinedbloom we are just calling the declare function. So the object will be the window object. It doesn't have property petalCount so its undefined.
In the function bloom we are binding the this of LateBloomer to the declare function by which we will have access to the LateBloomer's object petalCount.
this in JavaScript is a very difficult to fathom at first.
MDN Link: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this
function LateBloomer() {
this.name = 'triven'; //simplified property
}
// Some thoughts we discuss main requirement.
LateBloomer.prototype.bloom = function() {
window.setTimeout(function() {console.log(this);}, 1000); //Logs window: We all know that keyword this INSIDE CALLBACK
//function refers to Window [Comment 1]
//window.setTimeout(console.log(this), 1000); /Attentions: Here it is very easy to MISUNDERSTAND
//that keyword this is inside setTimeout and it should refer to window.
//Please note that here keyword this is not INSIDE CALLBACK function so here
//keyword this will refer to object on which its wrapper function is
//executed(in our case flower). [Comment 2]
};
//The requirement: We need to call .bloom and it should log name after 1 second.
LateBloomer.prototype.bloom = function() {
//here keyword this refers to object
//window.setTimeout(function() {console.log(this);}, 1000); //But inside callback keyword this refers to window.
};
//We need some way to access object inside call back function so that its name can be accessed after 1 sec.
//step 1; Taking out anonymous function and adding it as a prototype property
LateBloomer.prototype.bloom = function() {
//window.setTimeout(this.callback, 1000); //Note: Keyword this is not inside callback so
//it is referring to object (not window). We can access newly
//defined function on the object. Also keyword this placed inside callback
//function(below) will still refer to window.
};
LateBloomer.prototype.callback = function() {console.log(this.name);}
//step 2; bringing .bind into picture.
//Definition of .bind as per MDN : The bind() method creates a new function
//that, when called, has its this keyword set to the provided value
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.callback.bind(this), 1000); // Okay now we are now invoking .callback method on the object and
//passing the same object to bind.
// The keyword this inside newly return function (as a result of bind) will now refer to object
// we passed as argument to bind and we should not be able to access name property of our object.
// Note : Here both this keywords refers to same object ie on which which are calling .bloom.
//Note : we are no longer using passing callback function defined below. Instead we are now passing
// and exact copy of it but configuring it in such a way that keyword this start refering to object we passed.
};
LateBloomer.prototype.callback = function() {console.log(this.name);}
I want to be able to see the value inside callback function which was available when an event was bound. If function is defined when the event is bound then inside the function I can see the value through closure:
var number = 777;
$('span').click(function() {
alert(number); //alerts 777 - available through closure
});
But if the function is defined previously when the 'number' variable was unavailable, the trick won't work. The function number_alerter can't see the 'number' variable if the function is bound to the event in this way:
$('span').click(number_alerter);
It seems that the only solution is to define the function with the 'number' argument and pass the 'number' varible to the function:
//function defined somewhere earlier
function number_alerter(e, number) {
alert(number);
}
...
//current scope
var number = 777;
$('span').on('click', function(e) {
return number_alerter(e, number);
});
My question is whether there is another way to pass this varible to the 'number_alerter' function? Maybe it's also possible through closure?
EDIT:
Here is the real case when the above described might be needed. I have two functions:
array_sort(array, compare_function)
compare_values(value1, value2, case_insensitive)
The function array_sort passes to compare_values function only two values, while 3rd case insensitive parameter should be also passed when using the function array_sort. The only way I know how to do that is to wrap compare_values function into another function:
var my_array = [];
var case_insensitive = true;
var wrapper = function(value1, value2) {
compare_values(value1, value2, case_insensitive)
}
array_sort(my_array, wrapper);
Is there any other way I can do that?
You can use number_alerter to return the callback function, and use a closure. Like this
function number_alerter(num) {
return function(){alert(num);};
}
// different scope
var number = 777;
$('span').on('click', number_alerter(number));
See jsFiddle
Your problem has to be elsewhere. As far as you describe it, the following
var number=777;
var alerter=function(){
alert(number);
};
$("span").click(alerter);
works just fine. Cf. the JSFiddle
And, yes, if you need to have access to a defined state (e.g. you define a click-counter for every span) of a variable, it would be done best it with closures.
Edit: Oh, I see
$('span').click(
(function() {
return number_alerter})());
That's not the way to do it. you have to pass the function name at this point.
Refering to How do JavaScript closures work?.
Closure is:
a closure is the local variables for a function — kept alive after the function has returned, or
a closure is a stack-frame which is not deallocated when the function returns (as if a 'stack-frame' were malloc'ed instead of being on the stack!).
Just want to confirm are the following consider closure?
1) Binding javascript function within a function.
var Books = {
init:function(){
$('#box').bind('click',function(){
console.log('click');
});
}
};
Books.init();
2) Declare a function within a function
function sayHello(name) {
var text = 'Hello ' + name;
var sayAlert = function() { alert(text); }
}
var hello = sayHello();
I still can't differentiate which is closure for some times, is that all function within function consider closure or only the one that keep the returned inner function as variable/reference. Example:
function sayHello(name) {
var text = 'Hello ' + name;
var sayAlert = function() { alert(text); }
**return sayAlert;**
}
1 isn't as no variables are actually referenced, 2 and 3 are.
In 2 and 3 the variable called text is closed off - referenced outside its lexical scope. In 1 nothing is.
crockford on closures :
What this means is that an inner function always has access to the
vars and parameters of its outer function, even after the outer
function has returned.
All of those are closures.
I'm not sure what your confusion is.
function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
var ctr = getCtr();
ctr();
ctr();
I've been using Javascript from last five years, but this question made me dumb in last interview. I tried everything to my knowledge but can't figure it out.
Can you please help me with the output and reason for it so that I can be better equipped for future interviews if I have one.
var ctr = getCtr();
This calls getCtr(), which initializes i to 0, and stores a reference to the function
function() {
console.log(++i)
}
in ctr. Because that function was created in the scope of getCtr(), the variable i is still accessible in the scope of the function stored in ctr.
The first call to
ctr()
executes console.log(++i) which has a preincrement on i, so it prints out 1. The second call executes the same code, with the same preincrement, and prints out 2.
DISCLAIMER: Not a javascript developer. Forgive me if I've made an error or used some unpreferred wording.
So the code you posted outputs 1 2. Yet the code:
function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
getCtr()();
getCtr()();
outputs only 1 1!
The difference is that if you save a reference to getCtr() by using the var ctr = getCtr();, you create what is called a closure.
So the difference between calling getCtr()() and ctr() is that ctr has i defined in its scope, and that scope is saved thanks to var ctr = getCtr();. Because the reference is saved, the function inside of ctr is able to always act on the same variable.
run this:
var m=0;
var d=0;
alert(m++ +":"+ ++d);
and you get "0:1"
IF it were me asking in an interview, the difference in where the ++ is is what I would be after :)
http://jsfiddle.net/MarkSchultheiss/S5nJk/
Closures
The return statement in that function saves i. So when var i = 0; is only called var ctr = getCtr();. Then ctr becomes the returned function:
function () {
console.log(++i)
}
and the variable ctr has i in the scope of the outer function, getCtr() and the return function is in the scope of getCtr() as well.
okay, getCtr is a function that returns an other function.
It also contains a var called "i" which is set to 0.
"i" is also available in the scope of the returned function.
the preincrement of "i" before logging it to the console causes that it increases by 1 every time the returned function, which is stored in "ctr", is called.
When executed, function getCtr returns an inner anonymous function.
This function is now referenced by variable ctr
Because the anonymous function was created inside getCtr it will have access to getCtr private scope object, which contains variable 'i'. This is known as a closure.
var ctr = getCtr()
Every time the anonymous function is executed it pre-increments i, and writes in in the console.
ctr()
Lets break it down using terms you might know from classical inheritance based OOP languages:
// In javascript functions are first-class objects
// This function is being used like a class would be in Java
function getCtr(){
// You can think of this as a private variable of the getCtr "class"
var i = 0;
// Because it is returned, this is effectively a public method of getCtr
return function(){
// Which increments i and then prints it.
console.log(++i);
}
}
// This makes the variable ctrl an instance of getCtr.
var ctr = getCtr();
// This calls ctr's only public method.
ctr();
ctr();
So the output would be "1, 2".
What this question is meant to do is test if you understand Javascript's prototypal inheritance, ability to have anonymous functions, and closures.
A clarified version of that could that would do the same thing would be:
var myProtoype = function() {
var privateVariable = 0;
var privateMethod = function () {
privateVariable++;
console.log(privateVariable);
}
return {
publicMethod: privateMethod
};
}
var myInstance = new myPrototype();
myInstance.publicMethod();
myInstance.publicMethod();
That function is a Javascript Module. You can have a good reading about it on Javascript: the Good Parts, which is a great book and I highly recommend. A Module uses Javascript closures to create private variables and if assigned to a var the var will retain it's vars each time it's called instead of redefining the vars.
A module works like this
function moduleName(privateVar1){
var privateVar1;
var privateVar2;
return {
exposedFunction1: function (var1) {
// Do stuff... using private vars
return something;
},
exposedFunction2: function (var1, var2) {
// Do stuff...
return something;
}
}
}
var moduleInstance = moduleName(privateVar1);
moduleInstance.exposedFunction(var1);