题目1:[javascript]view plaincopyprint?vara=[1,2,3];varlen=a length;for(___){setTimeout{function(){console log(__);},0}}要求输出a

题目1:

 

  1. var a=[1,2,3];  

  2.         var len=a.length;  

  3.         for(___){  

  4.             setTimeout{

    function(){  

  5.                 console.log(__);  

  6.             },0}  

  7.         }  

  8.           

 

要求输出a的所有项。

该题目考察的就是的单线程以及setTimeout的异步特性。

【注】:JavaScript引擎是单线程运行的,浏览器运行期间只有一个线程在运行js程序。浏览器的内核是多线程的,他们在内核控制下相互配合,以保持同步,一个浏览器至少实现三个常驻线程:JavaScript引擎线程,GUI渲染线程,浏览器事件触发线程。

  • JavaScript引擎是基于事件驱动单线程执行的,js引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个js线程在运行js程序。

  • GUI渲染线程负责浏览器界面的渲染,当界面需要重绘的时候或者由于某种操作引发回流时,该线程就会执行,需要注意GUI渲染线程与js引擎是互斥的,当js引擎执行的时候GUI线程会被挂起,GUI更新会被保存在一个队列中,等到js引擎空闲时立即被执行

  • 事件触发线程,当一个事件被触发时该线程会把事件添加到待处理的队列末尾,等待js引擎的处理。这些事件可来自js引擎当前执行代码块,如setTimeout,也可来自浏览器内核的其他线程如鼠标点击、ajax异步请求等,但由于js的单线程关系所有这些事件都得排队等待js引擎处理。

  • 当线程中没有任何同步代码的前提下才会执行异步代码。

 

在上题中setTimeout是异步的代码,即使setTimeout中设置的等待时间为0也不会立刻执行,for循环代码是同步,所以要等待for循环执行完以后才会执行setTimeout。因此此时如果使用传统的for循环,在setTimeout中打印a[i]的话会出现undefined的情况。此时可以在for循环外定义一个局部变量j。打印的时候打印a[j++]就可以实现a数组的遍历

 

代码如下:

 

  1. var a=[1,2,3,4];  

  2.             var i,len=a.length;  

  3.             var j=0;  

  4.             

    "code"

     name= class="javascript">for(i = 0; i < len; i++) {  

  5.                 (function(i) {  

  6.                     setTimeout(function() {  

  7.                         console.log(a[j++]);  

  8.                     }, 0);  

  9.                 })(i)  

  10.             }  

 

 

或者

 

 

  1. for(i = 0; i < len; i++) {  

  2.                 (function(i) {  

  3.                     setTimeout(function() {  

  4.                         console.log(a[i]);  

  5.                     }, 0);  

  6.                 })(i)  

  7.             }  

 

 

题目2:

 

 

  1. for(var i = 1; i <= 3; i++) {  

  2.                 setTimeout(function() {  

  3.                     console.log(i)  

  4.                 }, 0)  

  5.             }  

  6.             //4,4, 4  

上面这个代码块会打印三个 `4` 出来,而我们预想的结果是打印 1 2 3 。
之所以会这样,是因为 setTimeout 中的 i 是对外层 i 的引用。当 setTimeout 的代码被解释的时候,运行时只是记录了 i 的引用,而不是值。而当 setTimeout 被触发时,三个 setTimeout 中的 i 同时被取值,由于它们都指向了外层的同一个 i,而那个 i 的值在迭代完成时为 4,所以打印了三次 `4`。
为了得到我们预想的结果,我们可以把 i 赋值成一个局部的变量,从而摆脱外层迭代的影响。

 

 

  1. for (var i = 0; i <= 3; i++) {  

  2.   (function (idx) {  

  3.     setTimeout(function () {  

  4.       console.log(idx);  

  5.     }, 5);  

  6.   })(i);  

  7. }  

或者:

 

  1. var j=0;   

  2. for(i = 0; i <=3; i++) {  

  3.             (function(i) {  

  4.                 setTimeout(function() {  

  5.                 console.log(a[j++]);  

  6.                 }, 0);  

  7.             })(i)  

  8.         }  

想要交流加QQ:3252897743