当前位置:网站首页>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.
边栏推荐
- [rust notes] 16 input and output (Part 1)
- Appium基础 — 使用Appium的第一个Demo
- One question per day 1447 Simplest fraction
- LeetCode 1200.最小绝对差
- Collection: programming related websites and books
- Solution to game 10 of the personal field
- Error ora-28547 or ora-03135 when Navicat connects to Oracle Database
- Sqlmap tutorial (II) practical skills I
- QQ computer version cancels escape character input expression
- One question per day 1765 The highest point in the map
猜你喜欢
Full Permutation Code (recursive writing)
Wazuh開源主機安全解决方案的簡介與使用體驗
可变电阻器概述——结构、工作和不同应用
Personal developed penetration testing tool Satania v1.2 update
Data visualization chart summary (II)
Introduction and experience of wazuh open source host security solution
Overview of variable resistors - structure, operation and different applications
Smart construction site "hydropower energy consumption online monitoring system"
Appium基础 — 使用Appium的第一个Demo
Erreur de connexion Navicat à la base de données Oracle Ora - 28547 ou Ora - 03135
随机推荐
Personal developed penetration testing tool Satania v1.2 update
Daily question 2006 Number of pairs whose absolute value of difference is k
QQ电脑版取消转义符输入表情
leetcode-31:下一个排列
MatrixDB v4.5.0 重磅发布,全新推出 MARS2 存储引擎!
Daily question 1688 Number of matches in the competition
数据可视化图表总结(二)
leetcode-1200:最小绝对差
leetcode-9:回文数
2022年贵州省职业院校技能大赛中职组网络安全赛项规程
leetcode-6110:网格图中递增路径的数目
On the characteristics of technology entrepreneurs from Dijkstra's Turing Award speech
Fried chicken nuggets and fifa22
从Dijkstra的图灵奖演讲论科技创业者特点
Daily question 2013 Detect square
【Rust 笔记】16-输入与输出(上)
1.15 - 输入输出系统
The difference between CPU core and logical processor
1039 Course List for Student
liunx启动redis