what's the statement execution order of this JS closure ? [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I have known the key of closure is about scope. But I don't know the specific execution order of it.
A classical code from 《Professional JavaScript for Web Developers 3rd Edition》about closures.
function createFunctions(){
var result=new Array();
alert('haha');
for(var i=0;i<10;i++){
result[i]=function(){
alert(i);
return i;
};
}
return result;
}
var a=createFunctions();
To my surprise, 'haha' was alerted while none of 'i' were alerted.I was just assigning the function to variable a.Why the statement "alert('haha')" was alerted while the cycle wasn' t executed?
when I add the below code,
var a=createFunctions();
alert(a[2]);
why it alerted like this
function (){
return i;
}
not like
function (){
return 2;
}
Furthermore when I add the below code, what will being the order of statements executed especially the statements in the cycle.
var a=createFunctions();
alert(a[2]());

When you call
var a=createFunctions()
alert('haha') is executed immediately, and an array of 10 functions is created and assigned to the variable 'a', each function alerting 'i' and returning it.
However, by the time any of those functions is called (provided you call them after creating them) the value of i is '10' (the loop termination value). So every time you call one of the functions, with
alert(a[x]())
( with any value of x = 0 thru 9 )
it will alert(10) as the function executes and alert(10) again when it returns.

Why the statement "alert('haha')" was alerted
Because it was an alert statement in the function you called.
while the cycle wasn' t executed
The cycle was executed. The cycle just creates some functions and assigns them to positions in an array. You never call any of those functions.
and when I add the below code, what will being the order of statements executed
It depends where you add it.

Related

Javascript -What happens if a variable and a function have the same name? [duplicate]

This question already has answers here:
Function and variable with the same name
(2 answers)
Closed 5 years ago.
Might be a kind of easy question, but I have a question on the issue of having the same name for a variable and a function.
If there's a variable,
var add = 1;
and a function,
function add(x,y) {return x+y;}
and there're two console.log,
console.log(add)
console.log(add(1,2))
I've expected those 2 console.log would work properly since add contains the Number and add() is classified as a Function, but the second one prints an error. So they aren't considered the same.
But the result says I'm wrong.
Can anyone explain what's going on in my code?
Variables and function definitions(not expressions) are hoisted to up, it means that wherever in scope you wrote your function or variable they will be moved to the start of the scope. First goes functions definitions then variables. So it means that functions will be overwritten by variables.
var add = 1;
function add(x,y) {return x+y;}
console.log(add);
The order doesn't matter. Later will be the variable and will overwrite
function add(x,y) {return x+y;}
var add = 1;
console.log(add);

Why do functions defined in a loop all return the same value? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
I'm confused by the following JavaScript code. I wrote a loop and defined a function inside the loop, but when I call a function defined in the loop, I only get 10 rather than the index.
Obviously, in the following code I abstracted out stuff that isn't relevant:
objectArray = [];
for (i = 0; i< 10; i++){
objectArray[i] = {};
}
for (i = 0; i< 10; i++){
objectArray[i].get_number = function(){
return i;
}
}
console.log(objectArray[5].get_number()); // returns 10 rather than 5
I always get 10 rather than i as expected.
It's because of JavaScript closure. The method objectArray[i].get_number has direct access to i (not a copy of i). The value of i lives on in memory because each method objectArray[i].get_number still has access to it. There's only one i, and when the loop iterates it, it increases by one. When a method objectArray[i].get_number accesses it, the loop has already run to completion, so it accesses the final value of i.

Immediately Invoked Function Expression use case:inadvertent sharing via closures [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
var result=[];
for(var i=0;i<5;i++){
result.push(function () {return i});
}
console.log(result[1]()); //5 not 1
I think the result should be [0,1,2,3,4] and I don't understand why the value should be 5. How does it work? I am completely confused.
Because JavaScript does not have block scope, it has function scope. There is only one i variable, and it exists for the whole function. It is changed from 0, to 1, and so on, up to 5. All of the closures reference this same variable.
You can fix it by passing the value in to an immediately-invoked function that returns another function:
result.push((function (i) { return function() { return i; } }(i));
In this case you pass the value of i in to the outer function, which returns another function that returns the argument to this inner function, effectively capturing the value of the outer i at that particular moment.

Why shouldn't I make functions within a loop in Javascript? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
In JavaScript, what are specific reasons why creating functions within a loop can be computationally wasteful?
(2 answers)
Closed 8 years ago.
I checked over my script the other day with JSFiddle and got a warning on one of the lines: Don't make functions within a loop.
for (x = 0; x < 10; x++) {
if (moment(now) > moment(then)) {
doIt(x); // do it now
} else {
timeTillEnd = moment(then) - moment(now);
setTimeout(function () {
doIt(x); // do it later
}, timeTillEnd); // <-- flagged here
}
}
Why shouldn't I make functions within a loop in Javascript?
Also: Could the usage of a function in the particular situation shown here be problematic?
What you are trying to do is probably wrong, the x variable might not be what you expect it to be. See the following link:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures#Creating_closures_in_loops.3A_A_common_mistake
And they are also relatively expensive to create.
Each function comes with the closure of the variables it uses, that is an unnecessary overhead if you are doing "normal imperative programming" and just want to make the code look clearer by defining inner functions for sub-tasks:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures#Performance_considerations
In your case, it seems that you actually need a function with its closure, since you are deferring some computation, but make sure that you do the proper value capture.
Because it can lead to unexpected closure behaviour (the captured variable will have the value assigned in the last iteration of the loop). You will also get a new instance of the function for each loop which is wasteful of resources.
Modern browsers take a third argument for setTimeout which is the argument to the function. See here. This also gets rid of the problems with closures.

Passing arguments to javascript function [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript closure inside loops - simple practical example
javascript variable scope/closure in loop after timeout
Can you please explain step by step why the results are different?
Snippet A (alerts 10)
for(var i=0; i<10; i++) if(i==3) setTimeout(function() {alert(i);}, 100);
Snippet B (alerts 3)
for(var i=0; i<10; i++) if(i==3) setTimeout((function(p) {
return function() {alert(p);}
} )(i), 100);
A variable's scope is either the global scope (window in a browser) or a function.
In the first case i is defined in the scope containing the for loop. This is why it still changes until the end of the loop before the callback given to setTimeout is executed.
In the second case, the intermediate function contains and keeps another variable, p. Note that this would have worked without the test, as this would have been a different closure for each setTimeout.

Categories