When I ran this code, I got a strange result
functionprintFive(){
for(vari=0;i<5;i++){
setTimeout(function(){
console.log(i);
}, i*1000);
}
}
printFive();
If you do this,
0
1
2
3
4
If you think is going to output slowly, it's actually
5
5
5
5
5
has come out.
Why do you loop from 0
to 4
, but only 5
appears?How can I get my way?
See I want to define what happens when I click with the for statement
The answer is the same as this.
The value must be bound by an immediate function within the for statement. See here for more information.
http://mattn.kaoriya.net/software/lang/javascript/20110523124612.htm
In such cases, it is easy to bind the value of i as with ({i:i}):
functionprintFive(){
for(vari=0;i<5;i++) with({i:i}){
setTimeout(function(){
console.log(i);
}, i*1000);
}
}
Description:
The closure (as other answers show) maintains a reference to variable i (rather than capturing the declared value).Therefore, if the contents of the outer i are rewritten after the closure is generated, the rewritten value can also be seen from the closure.Furthermore, if one closure rewrites variable i, another closure will also see its rewritten value.
where with({i:i})
creates an object called {i:i}
for each loop (an object whose member i has the value of vari at that time).Then with(...)
replaces the i
visible from the closure with the member of the object generated for each loop.
(But no one else has this kind of answer...) I sometimes use this method, but is there a problem?…)
# This is my first post, but can I post like this?
The above results are due to Closure.
Simply put, the variables that appear when a function is running are the same wherever it is, even if they are used by the function in it.
In setTimeout
, i
is exactly the same variable as i
outside setTimeout
.So if the value of i
on the outside changes, so does the value of i
on the inside.
The function passed to setTimeout
runs after the for
loop.Once executed, the i
value is displayed at that time. After the for
loop, the i
value is 5
, so 5
appears five times.
There are several ways to view 0
, 1
, 2
, 3
, 4
as you wish.
One way is to call another function to create a new variable.
functionprintFive(){
for(vari=0;i<5;i++){
setTimeout (makePrintFunction(i), i*1000);
}
}
function makePrintFunction(value) {
return function() {
console.log(value);
}
}
printFive();
Each time makePrintValue
is invoked, a new variable called value
is generated and a function using that variable is returned.Therefore, if the i
value changes, the value
value does not change.
Another way is to use bind
.
functionprintFive(){
for(vari=0;i<5;i++){
setTimeout (printValue.bind(null, i), i*1000);
}
}
function printValue(value) {
console.log(value);
}
printFive();
bind
is a method that creates a new function by passing arguments in advance without running a function.The value passed at that point will be kept, so if the value of i
changes, the value already passed will not be affected.
Incidentally, in this case, you can call bind()
directly to console.log
:
functionprintFive(){
for(vari=0;i<5;i++){
setTimeout(console.log.bind(null,i),i*1000);
}
}
printFive();
It's been a while, but if you want to use js, I think you should be able to use recursive properly, so I will paste a sample code using recursive.
At some point, there is only one setTimeout running at the same time, so it's easy to stop.
<html>
<script>
( function printFive (loop, now) {
if(!now)now=0;
if(loop<now)return true;
setTimeout(function(){
now++;
console.log(now);
This(loop, now);
}.bind(printFive), 1000);
})(5)
</script>
</html>
© 2024 OneMinuteCode. All rights reserved.