当前位置:网站首页>In depth analysis of for (VaR I = 0; I < 5; i++) {settimeout (() => console.log (I), 1000)}
In depth analysis of for (VaR I = 0; I < 5; i++) {settimeout (() => console.log (I), 1000)}
2022-07-05 06:08:00 【weixin_ forty-one million three hundred and eighty-seven thousa】
A common question
for(var i = 0;i < 5;i++)
{
setTimeout(() => console.log(i),1000);
}
For this question , I'm sure you've heard about it , The final output is
5 5 5 5 5
without doubt , This is inconsistent with our expected output ( The expected output is 0 1 2 3 4). The reason for this problem , Namely var The scope of the identifier declared by the keyword is the function scope .
So in the above js In the code ,i Identifiers are stored in the global scope . therefore , When setTimeout When the callback function of ,i The value stored in the identifier is 5 了 (5 It is the end of the cycle ), So... Will be output 5 individual 5.
But here is another doubtful point , Why? setTimeout When it comes to execution i It's already 5 了 , Because I waited 1 Seconds ?
setTimeout Execution time of
Now we know the answer to the first question and the reason for the mistake , What about the following question
for(var i = 0;i < 5;i++)
{
setTimeout(() => console.log(i),0);
}
In fact, the output of this problem is also
5 5 5 5 5
This output actually tells us the answer to our doubts just now , Not because of waiting 1 Seconds cause setTimeout When it comes to execution i The value stored in becomes 5.
So what's the reason ?
We can read this code carefully , We found that for A loop is a synchronization code , and setTimeout It's asynchronous code .
So that's it , We immediately associate the cycle of events , Event loops can help us distinguish the execution timing of synchronous code and asynchronous code . The event loop is simply to execute the macro task first , Then empty a cycle of the micro task queue .
The common macro tasks are
- <script> All synchronization codes under the tag
- setTimeout、setInterval
- I/O
- UI Interaction
Common micro tasks are
- Promise Related methods
therefore js The engine is doing this for In the cycle , Yes setTimeout, Will be setTimeout Put in the macro task queue , Then execute the synchronization code , When the synchronization code is executed, check the micro task queue , Only when the next round of event cycle begins setTimeout Remove... From the macro task queue .
therefore ,setTimeout The execution of must be in all synchronous code , That is the whole for After the execution of the loop , So in setTimeout When it comes to execution ,i It's already 5 了 .
resolvent
Now we have made clear the reason why the code output does not match the expectation , That's the scope .
First of all, it's easy to think of , If the identifier i Limited to block scope , You can solve the problem .
Use let
for(let i = 0;i < 5;i++)
{
setTimeout(() => console.log(i),1000);
}
setTimeout Callback function for () => console.log(i) The lexical scope of is for Block scope inside the loop . This function is specified as a callback function , without doubt , Will be called outside its lexical scope , And when it is called js The engine will be right i Conduct RHS quote , So even if for The loop has been executed , The scope of each layer of the loop is still () => console.log(i) maintain , therefore setTimeout When executing, you can access the loop of each layer i. This actually forms what we often call closures ( A function is called outside its defined lexical scope , And maintain the reference to the variables in the lexical scope it is defined ).
Use IIFE
IIFE yes Immediately Invoked Function Expression, Call function expression now .
for(var i = 0;i < 5;i++)
{
setTimeout((function(i){
return () => console.log(i);
})(i),1000)
}
Use here IIFE The purpose of is to use closures . Each layer circulates IIFE It is equivalent to creating a function scope for each layer of loop , And put each layer of circulation i The value of is passed in as a parameter , Store in IIFE In the identifier with the same name of the function scope of . And this IIFE take () => console.log(i) Returned as a value to setTimeout.
alike ,() => console.log(i) Is defined in IIFE Function scope of , It will be called outside its lexical scope , And in () => console.log(i) Maintain references to variables in its lexical scope ( ad locum , In fact, in the scope chain search of lexical scope ‘ Homonymous masking ‘ It also worked ).() => console.log(i) Function is called ,js The engine will be right i Conduct RHS lookup ,js The engine first asked () => console.log(i) The scope of its own function , No such identifier found , Then search rules according to lexical scope , Go to () => console.log(i) The upper lexical scope of , That is to say IIFE Function scope lookup identifier i, ad locum js The engine found the identifier i, So this closure exists ( Yes IIFE A reference to a scope ),setTimeout When executing, you can access the loop of each layer i.
边栏推荐
- PC register
- Personal developed penetration testing tool Satania v1.2 update
- 【实战技能】如何做好技术培训?
- [rust notes] 14 set (Part 1)
- 2017 USP Try-outs C. Coprimes
- 【Rust 笔记】13-迭代器(中)
- Convolution neural network -- convolution layer
- Full Permutation Code (recursive writing)
- CF1634E Fair Share
- QQ computer version cancels escape character input expression
猜你喜欢
数据可视化图表总结(二)
Open source storage is so popular, why do we insist on self-development?
Fried chicken nuggets and fifa22
QQ电脑版取消转义符输入表情
从Dijkstra的图灵奖演讲论科技创业者特点
On the characteristics of technology entrepreneurs from Dijkstra's Turing Award speech
Dynamic planning solution ideas and summary (30000 words)
leetcode-6111:螺旋矩阵 IV
智慧工地“水电能耗在线监测系统”
[jailhouse article] look mum, no VM exits
随机推荐
【Jailhouse 文章】Jailhouse Hypervisor
leetcode-1200:最小绝对差
Daily question 1342 Number of operations to change the number to 0
[rust notes] 13 iterator (Part 2)
【Rust 笔记】13-迭代器(中)
PC register
LeetCode 0107.二叉树的层序遍历II - 另一种方法
leetcode-556:下一个更大元素 III
Brief introduction to tcp/ip protocol stack
网络工程师考核的一些常见的问题:WLAN、BGP、交换机
[jailhouse article] jailhouse hypervisor
【Rust 笔记】16-输入与输出(上)
Personal developed penetration testing tool Satania v1.2 update
redis发布订阅命令行实现
AtCoder Grand Contest 013 E - Placing Squares
Navicat连接Oracle数据库报错ORA-28547或ORA-03135
2022 极术通讯-Arm 虚拟硬件加速物联网软件开发
RGB LED infinite mirror controlled by Arduino
Wazuh开源主机安全解决方案的简介与使用体验
Binary search template