当前位置:网站首页>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.
边栏推荐
- MIT-6874-Deep Learning in the Life Sciences Week 7
- 个人开发的渗透测试工具Satania v1.2更新
- Sqlmap tutorial (1)
- Appium基础 — 使用Appium的第一个Demo
- [rust notes] 14 set (Part 2)
- How many checks does kubedm series-01-preflight have
- [practical skills] how to do a good job in technical training?
- CF1634E Fair Share
- [jailhouse article] look mum, no VM exits
- Daily question 1688 Number of matches in the competition
猜你喜欢

Open source storage is so popular, why do we insist on self-development?

Time of process

redis发布订阅命令行实现

做 SQL 性能优化真是让人干瞪眼

传统数据库逐渐“难适应”,云原生数据库脱颖而出

CF1634 F. Fibonacci Additions

The connection and solution between the shortest Hamilton path and the traveling salesman problem

Scope of inline symbol

数据可视化图表总结(二)

【Jailhouse 文章】Jailhouse Hypervisor
随机推荐
wordpress切换页面,域名变回了IP地址
数据可视化图表总结(一)
剑指 Offer II 058:日程表
Annotation and reflection
Groupbykey() and reducebykey() and combinebykey() in spark
Open source storage is so popular, why do we insist on self-development?
How to adjust bugs in general projects ----- take you through the whole process by hand
EOJ 2021.10 E. XOR tree
Appium foundation - use the first demo of appium
【Rust 笔记】16-输入与输出(上)
2020ccpc Qinhuangdao J - Kingdom's power
[jailhouse article] performance measurements for hypervisors on embedded ARM processors
liunx启动redis
[practical skills] technical management of managers with non-technical background
Dynamic planning solution ideas and summary (30000 words)
个人开发的渗透测试工具Satania v1.2更新
Binary search template
【Rust 笔记】17-并发(下)
Control unit
2022 pole technology communication arm virtual hardware accelerates the development of Internet of things software