标签:git llb 开发 console 异步任务 red java strong blank
文章首发于 szhshp的第三边境研究所 ,转载请注明
先来看几道面试题,公司的开发们都尝试做了一下,然而基本没有人能够全部答对。
覆盖的考点很多,也有一些难度,题目挺有意思建议手动执行一边玩玩。
for (var i = 0; i <5 ; i++) { setTimeout(function(){ console.log(i) ),1000} } console.log(i)
for (let i = 0; i <5 ; i++) { //注意var变成了let setTimeout(function(){ console.log(i) },1000) } console.log(i)
A:这道题目其实是个坑。首先题目与Q1的区别就是变量i的定义改为了关键字let,使用let的时候会将变量限制在循环之中,因此第二个输出其实会报错。另外setTimeout实现了(伪)异步,同时因为let将变量作用域进行了控制,破坏了闭包结构,因此会按照正常顺序输出。
关于let关键字[^3]
Use the let statement to declare a variable, the scope of which is restricted to the block in which it is declared. You can assign values to the variables when you declare them or later in your script.
A variable declared using let cannot be used before its declaration or an error will result..
考点:闭包,(伪)异步,作用域
同样是Q1的代码
for (var i = 0; i <5 ; i++) { //DO NOT MODIFY setTimeout(function(){ //DO NOT MODIFY console.log(i) },1000) } console.log(i) //DO NOT MODIFY
A
其次考到了setTimeout事件队列的处理
for (var i = 0; i <5 ; i++) { (function(i){ setTimeout(function(){ console.log(i) },1000*i) })(i) //将i作为参数传入匿名函数,如此破坏了闭包内跨域访问 } setTimeout(function (){ console.log(i); }, 5000); //强行将5放到5sec后输出
考点:闭包,(伪)异步,作用域,事件队列
window.setTimeout(function (){ console.log(2) },1); //Ouput for a long time for (var i = 0; i < 1000; i++) { console.log(‘‘); }; console.log(1) window.setTimeout(function (){ console.log(3) },0);
这道题目其实是其他地方抄袭来的[^2],正好和之前考点有一定重叠因此一起放了过来:
setTimeout(function(){console.log(4)},0); new Promise(function(resolve){ console.log(1) //time consuming ops for( var i=0 ; i<10000 ; i++ ){ i==9999 && resolve(); } console.log(2) }).then(function(){ console.log(5) }); console.log(3);
A:输出是12354
关于这个输出,有如下几个逻辑:
一个事件循环(EventLoop)中会有一个正在执行的任务(Task),而这个任务就是从 macrotask 队列中来的。在whatwg规范中有 queue 就是任务队列。当这个 macrotask 执行结束后所有可用的 microtask 将会在同一个事件循环中执行,当这些 microtask 执行结束后还能继续添加 microtask 一直到真个 microtask 队列执行结束。
基本来说,当我们想以同步的方式来处理异步任务时候就用 microtask(比如我们需要直接在某段代码后就去执行某个任务,就像Promise一样)。
其他情况就直接用 macrotask。
规范:https://html.spec.whatwg.org/multipage/webappapis.html#task-queue
再来回顾下事件循环如何执行一个任务的流程
当执行栈(call stack)为空的时候,开始依次执行:
上面就算是一个简单的 event-loop 执行模型
再简单点可以总结为:
1. promiseA.then() 的回调就是一个 task 1. promiseA 是 resolved或rejected: 那这个 task 就会放入当前事件循环回合的 microtask queue 1. promiseA 是 pending: 这个 task 就会放入 事件循环的未来的某个(可能下一个)回合的 microtask queue 中 1. setTimeout 的回调也是个 task ,它会被放入 macrotask queue 即使是 0ms 的情况
[^3]: let 语句 (JavaScript) .aspx)
[^2]: https://www.zhihu.com/question/36972010
[^1]: https://github.com/ccforward/cc/issues/48
标签:git llb 开发 console 异步任务 red java strong blank
原文地址:http://www.cnblogs.com/gbin1/p/7456432.html