当前位置:网站首页>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.
边栏推荐
- SQLMAP使用教程(二)实战技巧一
- Daily question 1342 Number of operations to change the number to 0
- shared_ Repeated release heap object of PTR hidden danger
- The sum of the unique elements of the daily question
- 可变电阻器概述——结构、工作和不同应用
- One question per day 2047 Number of valid words in the sentence
- [rust notes] 15 string and text (Part 1)
- “磐云杯”中职网络安全技能大赛A模块新题
- CPU内核和逻辑处理器的区别
- Règlement sur la sécurité des réseaux dans les écoles professionnelles secondaires du concours de compétences des écoles professionnelles de la province de Guizhou en 2022
猜你喜欢
SPI 详解
Matrixdb V4.5.0 was launched with a new mars2 storage engine!
[practical skills] how to do a good job in technical training?
从Dijkstra的图灵奖演讲论科技创业者特点
Traditional databases are gradually "difficult to adapt", and cloud native databases stand out
Dichotomy, discretization, etc
CF1634E Fair Share
Introduction to LVS [unfinished (semi-finished products)]
[practical skills] technical management of managers with non-technical background
[article de jailhouse] jailhouse hypervisor
随机推荐
RGB LED infinite mirror controlled by Arduino
[rust notes] 14 set (Part 1)
leetcode-6108:解密消息
一些工具的记录2022
2017 USP Try-outs C. Coprimes
Traditional databases are gradually "difficult to adapt", and cloud native databases stand out
Codeforces Round #716 (Div. 2) D. Cut and Stick
2022年貴州省職業院校技能大賽中職組網絡安全賽項規程
个人开发的渗透测试工具Satania v1.2更新
[jailhouse article] jailhouse hypervisor
[article de jailhouse] jailhouse hypervisor
Navicat连接Oracle数据库报错ORA-28547或ORA-03135
数据可视化图表总结(一)
QQ computer version cancels escape character input expression
Introduction et expérience de wazuh open source host Security Solution
leetcode-3:无重复字符的最长子串
SQLMAP使用教程(二)实战技巧一
从Dijkstra的图灵奖演讲论科技创业者特点
927. Trisection simulation
A reason that is easy to be ignored when the printer is offline