I don't quite understand JS closures and I think it can solve my problem. here it is:
I have something like that :
$(document).ready(function () {
$("#buttonConfirm").click(function () {
popup_confirme();
});
});
function popup_confirme() {
var r = popup_modal();
}
function popup_modal() {
var int_val = 0;
$(".button").click(function () {
int_val = ($(this).val() == 'yes' ? '1' : '0');
});
return int_val;
}
I would like to get my int_val returned by the button click event. I need to get the 'r' value as 0 or 1. I know I should use closures, but I dont know how to do it. Thank you for your expertise !
You can't do this, it's impossible, for reasons unrelated to closures.
Your not calling the code that sets int_val, you're only defining the code, and saying "when .buttons are clicked, invoke this code". The code will not have been executed at the point you run return int_val, it will be executed at some point in the future when the button is clicked.
This block of code cannot logically work:
// First line run
var int_val = 0;
// Second line run
$(".button").click(function () {
// This line runs in the future, or maybe never, if the button isn't clicked
int_val = ($(this).val() == 'yes' ? '1' : '0');
});
// Third line run
return int_val;
If you want to communicate values back out of asynchronous functions, you should use promises:
function popup_modal() {
var dfd = $.Deferred();
$(".button").click(function () {
int_val = ($(this).val() == 'yes' ? '1' : '0');
// Allow int_val to find its way back to the calling code's `done` handler
dfd.resolve(int_val);
});
return dfd.promise()
}
The calling code will receive a promise object, which it can add callbacks to:
function popup_confirme() {
var r;
popup_modal().done(function (int_val) {
r = int_val;
}
}
I can't intuit beyond this point what you meant int_val to do up in your calling code.
A closure occurs when an inner function references something defined outside it. To illustrate:
function outer() {
var foo = 1;
element.click(function () {
// this function creates a closure on foo.
alert(foo);
});
};
What you seem to want done is that your int_val variable be accessible where both popup_modal and popup_confirme can get to it.
Many ways to do it based off your example, but something as simple as this can work:
(function () {
var int_val = 0;
var popup_modal = function () {
int_val = $(this).val() === 'yes' ? 1 : 0;
};
var popup_confirme = function () {
// your original code here doesn't really do anything
alert(int_val);
};
$('.button').click(popup_modal);
$('#buttonConfirm').click(popup_confirme);
}());
Technically all JavaScript functions are closures as they are objects with a scope chain attached to them. A closure is simply the combination of a function object and a scope (a set of variable bindings).
Scope is actually pretty simple really. Javascript uses lexical scoping which means that function are executed in the variable scope that was in effect when they were defined. Simply put, An outer function cannot read a value from an inner function unless is is specifically returned. An inner function can read all values declared in an outer function.
When most people talking about closures they are actually referring to the act of returning an item from an inner nested function to the outer function in which it has been defined.
e.g
// I am the outer function.
function outer (){
var outerVariable = "I am available to inner functions.";
// I am an inner function. I was declared in the scope of the outer
// function and as such all the variables declared in that scope are
// available to me.
function inner (){
// This will return => "I am available to inner functions." as we can
// read the outer declaration.
var innerReadValue = outerVariable;
// This will be available only to the inner function as it is
// not returned.
var privateVariable = "I am private";
// This will be available to the outer function as we are returning it
// on the next line.
var publicVariable = "I am available to outer functions";
// Make publicVariable public. This is what most people refer to
// when talking about closures.
return publicVariable;
}
// Read the inner functions publicVariable declaration.
// Returns => "I am available to outer functions"
var outerReadValue = inner();
}
In your example you are trying to get a value that was declared and not returned on the inner scope. As you should understand by now, this is invisible to the outer function so cannot work.
This can be rewritten as such:
// This is called an Immediately Invoked Function Expression. IIFE, It
// basically wraps your code in a function hiding all internal declarations
// from the global scope and then invokes it. You don't want to pollute the
// global scope.
(function(){
// Declare this outside so all functions can read it.
var int_val = 0;
// Declare this outside so all functions can read it.
var popup_confirm = function(){
// "int_val" is available here.
return int_val;
};
// Although your function runs automatically, we delay binding until
// the DOM is ready.
$(document).ready(function(){
$("#buttonConfirm").click(function(){
// Provide feedback. "popup_confirm" is available here
// since is declared in the outer scope.
return popup_confirm();
});
$(".button").click(function(){
// Set the value of int_val that has been declared in the outer
// scope.
int_val = $(this).val() === "yes" ? 1 : 0;
});
});
}());
Hopefully this makes it all a little bit more clear to you.
Related
I am learning how to reverse engineer an existing javascript code and I've ran into a few issues which is due to my lack of understanding how core javascript works. The code is below along with a screen shot of the comments I have.
The code starts out with var warper being declared.
And then warper variable equals a function inside a function? Why isn't it the usual call of function Warper(), but its inside another function?
I noticed the use of _this. How is that different from the regular this that is usually used?
The #btn-submit id is set to activate when it is clicked on. I can see that it calls the click_submit function, but why is it Warper.prototype.click_submit instead of just click_submit()?
And my final question, which is what I really want to do is call the click_submit function via js without having to click on the #btn-submit button.
Question: How do I call the warper.click_submit function using js without the need to click a button? I'm trying to integrate this into another piece of my code.
I tried warper.prototype.click_submit and it doesnt do anything. I'm assuming its because its inside a function in a function?
(function() {
var Warper;
Warper = (function() {
function Warper() {
this.check_compatibility();
this.attach_ux();
if (window.SALT_DEFAULT != null) {
$('#salt').val(window.SALT_DEFAULT);
$('#salt').attr('disabled', true);
$('.salt-label').text('Prefilled salt');
}
}
Warper.prototype.check_compatibility = function() {
if (typeof Int32Array === "undefined" || Int32Array === null) {
return $('.form-container').html('<p>\n Sorry, but your browser is too old to run WarpWallet, which requires Int32Array support.\n</p>');
}
};
Warper.prototype.attach_ux = function() {
$('#btn-submit').on('click', (function(_this) {
return function() {
return _this.click_submit();
};
})(this));
$('#btn-reset').on('click', (function(_this) {
return function() {
return _this.click_reset();
};
})(this));
return $('.what-salt').on('click', (function(_this) {
return function() {
return $('.salt-explanation').toggle();
};
})(this));
};
Warper.prototype.click_submit = function() {
$('#btn-submit').attr('disabled', true).html('Running...');
$('#btn-reset').attr('disabled', true).html('Running...');
$('#passphrase, #salt, checkbox-salt-confirm').attr('disabled', true);
$('.progress-pbkdf2, .progress-scrypt').html('');
$('.progress-form').show();
return warpwallet.run({
passphrase: $('#passphrase').val(),
salt: $('#salt').val(),
progress_hook: (function(_this) {
return function(o) {
return _this.progress_hook(o);
};
})(this),
params: window.params
}, (function(_this) {
return function(res) {
$('#passphrase, #checkbox-salt-confirm').attr('disabled', false);
if (window.SALT_DEFAULT == null) {
$('#salt').attr('disabled', false);
}
$('#private-key').val(res["private"]);
_this.write_qrs(res["public"], res["private"]);
return console.log;
};
})(this));
}; //click_submit
return Warper;
})(); // Warper End
$(function() {
return new Warper();
});
}).call(this); // End Function
The code starts out with var warper being declared.
And then warper variable equals a function inside a function? Why isn't it the usual call of function Warper(), but its inside
another function?
It is inside another function to create it's own scope. This practice is used mainly to separate non relative code and prevent global variables.
I noticed the use of _this. How is that different from the regular this that is usually used?
_this is just a variable that is set to point to outer this. Everytime you call a function it has own this (depending on how you called the function). So if define callback inside another function, and you need to refer to this of that outer ("another") function, you can save it temporarily to variable. This temporarily variables are usually referred to as _this, that or self.
The #btn-submit id is set to activate when it is clicked on. I can see that it calls the click_submit function, but why is it
Warper.prototype.click_submit instead of just click_submit()?
If you define function on prototype, every instance will use that same function. If you would define it on this.clik_submit = function(){...} then every instance would have to have it's own copy of that function. Last option is to just define function click_submit(){...} inside scope, but then the function wouldn't be accessible from outside the scope.
And my final question, which is what I really want to do is call the click_submit function via js without having to click on the
btn-submit button.
You need to gain access to warper instance to be able to call the click_submit function. Without it (and without being able to update the code) it is not possible to call it. But you could consider creating click event on button yourself which would trigger the function. Using jquery this is as easy as $("#btn-submit").click();
Warper is an object.
Warper.prototype.attach_ux = function() {
$('#btn-submit').on('click', (function(_this) { //2
return function() {
return _this.click_submit(); //3
};
})(this));//1.
on //1 'this' refers to the Warper object and is bound to the scope of Warper.prototype.attach_ux function.
on //2 _this is the name of argument which refers to the value passed at //1.
Since //1 refers to the Warper object the click_submit method is called.
This is IIFE pattern of function invocation.
If you were to call
$('#btn-submit').on('click', function(_this) {
return function() {
return _this.click_submit();
};
})
Here _this would refer to the click event and we would not be able to access the defined method conviniently. But we are able to pass the Warper object using IIFE pattern and access it easily.
i am starting to look at JS in more detail and after testing out some code i have come up with this situation:
var hello = function ()
{
console.log(arguments);
return (function(x,y){console.log(arguments);return x*y;});
}();
console.log(hello(2,5));
The output from the console is as follows:
[object Arguments] { ... }
[object Arguments] {
0: 2,
1: 5
}
10
Can someone please explain the behavior as i cannot get my head around it.
I understand the the first function is an IIFE and it is being executed immediately when it is created. My only problem is how does the passed parameters be passed to the internal function?
Thanks in advance for the information and comments
Alright, let me see if I can unwrap this for you:
var hello = function ()
{
console.log(arguments);
return (function(x,y){
console.log(arguments);
return x*y;
});
}();
console.log(hello(2,5));
First, I'm going to split out the IFFE into a function statement. It will work the same, but be more like traditional code:
// Create our function
function action(x, y) {
console.log(arguments);
return x*y;
}
var hello = function ()
{
console.log(arguments);
//Here we are returning a REFERENCE to a function that already exists.
// We are *not* running the `action` function -- just getting its
// reference so it can be called later.
return action;
}();
// At this point in time, if you did a
console.log(hello)
// You'd see that it just points to the `action` function -- since that is what the
// IIFE returned.
console.log(hello(2,5));
The value hello is now our action function.
The IFFE syntax has the following advantages:
Since it is an anonymous function, you aren't using a name or cluttering the global object.
The code is more "in-line" instead of being split into two separate pieces.
Might help, by the way, if I explain the difference between a function statement and a function expression.
A function statement looks like this:
function functionStatemnt() {
...
}
The functionStatement is available at compile done. That code doesn't need executed in order to be available.
A function expression is more like:
var functionExpression = function() {
...
};
And an IFFE is a function expression that immediately invokes. Gives you a way to create a scope and "hide" variables.
var myCounter = function() {
var counter = 0;
return function() {
return counter++;
}
}
console.log(myCounter());
console.log(myCounter());
console.log(myCounter());
I do not yet have a basic understanding of JavaScript closures;
I have a question regarding a specific situation that perhaps is also basic and common example:
Count from 1 to 3 in 3 seconds
See JSFiddle here: http://jsfiddle.net/nAh8x/
The code:
var i,
t;
t = 0;
// Case A
for( i=1; i<=3; i++ ) {
setTimeout( function() { log(i); }, t );
t += 1000;
}
// Case B
for( i=1; i<=3; i++ ) {
setTimeout( wrapper(i), t );
t += 1000;
}
function wrapper(i) {
return function() { log(i); };
}
// Log utility function
function log(msg) {
$('#log').append( msg + '<br />' );
}
Case A doesn't work.
It's clear to me why: every time the function inside setTimeout is called and accesses the i variable, its value has already reached 4.
Case B works.
When wrapper(i) is called it returns
function() { log(i); };
and the above return value (a function) is what goes inside setTimeout. What goes inside setTimeout is exactly the same as Case A
But this time, the i variable have been "frozen" with the value at the time of the call.
Why using the wrapper function let the passed value to be frozen?
That's not completely clear to me.
Closure is an environment which is created with variables scope and nested function by calling of outer function,
Every time the wrapper() is called there would created each different environment for below's function
function wrapper(i) {
return function() { log(i); };
}
Here is the i's value would be same as when wrapper() is invoked. Each time the i's value would be private for that particular environment which made by invoking wrapper() outer function.
The wrapper function has it's own i that is locally scoped to it.
This receives the value of the other i at the time wrapper is called.
It might be clearer if you rewrote it as:
function wrapper(notI) {
return function() { log(notI); };
}
The variable i used inside wrapper is the one the has been passed (as a copy) as the formal parameter to wrapper. It's not the same i as the one inside your for loop - you could rename that variable to anything you like and the code would still work.
It's frozen because it has the value it had each time wrapper was originally called.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
setTimeout and “this” in JavaScript
I am trying to put a timeout on an Object. With some test code (see below) I want to decrease the timerPos until it reaches 0. When I use the code below the first time timerInc() is called by startTimer(), it will reach 3 (as expected). When TimerInc() is called by the timeout i will receive 'undefined' for the timerPos variable. What am I doing wrong?
function start(){
var alert = new Alert(3);
alert.startTimer();
}
function Alert(timer) {
this.timerMinutes = timer;
this.timerPos = 0;
this.startTimer = function() {
this.timerPos = this.timerMinutes+1;
this.timerInc();
};
this.timerInc = function() {
if (this.timerPos > 0){
this.timerPos--;
// first time this function gets called timerPos is 3
// the second time when its called by the timeout it
// will be 'undefined'
setTimeout(this.timerInc,1000);
}
};
}
(using this.timerInc() in the timeout instead of this.timerInc does not work for me, neither does using quotes)
You need to bind the "this" variable to another one that you use explicitly since the value of "this" changes based on who is calling the function!
function Alert(timer) {
var that = this; // Store this Alert instance as "that".
this.timerMinutes = timer;
this.timerPos = 0;
// ...
this.timerInc = function() {
// Use the Alert instance "that", not whatever is bound to "this" at runtime.
if (that.timerPos > 0){
that.timerPos--;
setTimeout(that.timerInc, 1000);
}
};
}
The issue is that the setTimeout() function will call its function argument from global scope, not the scope of the enclosing object at the time it is registered. So in global scope the "this" variable is bound to the "global" object (likely the browser window).
You can verify like so:
setTimeout(function(){alert(this);}, 500); // => alerts "[object DOMWindow]"
First of all you should use prototype to declare the methods of your class Alert. And changing the scope of the function you're calling is gonna do the job:
function start(){
var alert = new Alert(3);
alert.startTimer();
}
function Alert(timer) {
this.timerMinutes = timer;
this.timerPos = 0;
}
Alert.prototype.startTimer = function() {
this.timerPos = this.timerMinutes+1;
this.timerInc();
};
Alert.prototype.timerInc = function() {
if (this.timerPos > 0){
this.timerPos--;
console.log(this.timerPos);
setTimeout(function(_this){_this.timerInc()},1000,this);
}
};
DEMO: http://jsfiddle.net/kmendes/HNYKa/1/
I have often see expressions such as:
(function () {
var x = 1;
...
}());
How do I interpret it? syntactically, this alone is a anonymous function definition.
function() {
...
}
what the () after that? and why put it in the enclosing ()?
Thanks
Exactly the same, except that it is being invoked immediately after being converted into a function expression.
// v-----first set of parentheses makes the function an expression
(function () {
var x = 1;
...
}());
// ^-----this set is used to invoke the function
Same as if you did:
var myfunc = function () {
var x = 1;
...
};
myfunc();
or (similar) this:
var returnValue = function () {
var x = 1;
...
}();
Get rid of the names, move the parentheses around, and you can see they're not that different.
The area where I most often find this useful is in callback functions. This notation can also used in cases where you need to include a variable in a callback function, but you need the variable state to not be affected by what goes on outside the function.
var someVal = 1;
setTimeout( (function(one) {
return function() {
alert(one); // alerts a 1 even 10 seconds after someVal++;
}
})(someVal), 10000);
someVal++; // the value in the setTimeout will remain the same as it is locked inside.
In this context, setTimeout takes a function that takes no arguments. So the question of how to pass in a value to that function is answered by creating a function that takes one argument that returns a function that takes 0 arguments.
I suggest anyone wanting to learn more about the power of this notation to play around with it in the Firebug JavaScript console. Once you wrap your head around this concept, you'll start to see areas where this powerful concept can be used.