一個setTimeout問題小探索

問題

以前有提到一個異步問題,以下代碼輸出什麼:es6

for(var i = 0;i<10;i++){
  setTimeout(function(){
    console.log(i);  
  },1000);
}

這是我近期遇到的一個面題。當時我並不知道。不事後來面試官告訴我,setTimeout是異步執行的。而且告訴了我答案。後來在羣裏邊討論,明白了。會輸出10個10。面試

探索

爲何呢?首先,setTimeout是異步執行的。因此在setTimeout執行以前,全局變量i早就已經變成了10。chrome

那麼如何解決能讓他輸出0-9呢?其實要解決的就是:在使用i的時候保證i的值仍是咱們當時但願的那個值。segmentfault

若是不考慮兼容性,咱們可使用es6的let,把每一個i變成一個局部變量。代碼以下:promise

for(let i = 0;i<10;i++){
  setTimeout(function(){
    console.log(i);  
  },1000);
}

若是要考慮兼容性,那麼咱們用一個匿名函數,把i當作參數傳進去,這樣咱們再用的i就是局部變量了。不會受到外邊的影響了。代碼以下:異步

for(var i = 0;i<10;i++){
  (function(i){
    setTimeout(function(){
      console.log(i);  
    },1000);
  })(i)
}

若是使用promise,那麼咱們可使用以下寫法:函數

for(var i = 0;i<10;i++){
  let a = i;
  let p = new Promise((resolve,reject)=>{
    setTimeout(()=>{resolve(a)},1000);
  });
  p.then(i=>console.log(i))
}

思考

可能這種promise方法更麻煩了。可是適用於更復雜的需求了。假設setTimeout的時間是一個隨機數。而咱們要在全部數字都打印完畢再去作一些操做,那麼該怎麼作呢?
具體能夠參見:https://segmentfault.com/a/11...code

執行效率上的考慮:blog

console.time('a');
for(let i = 0;i<10;i++){
  setTimeout(function(){
    console.log(i);  
  },1000);
}
console.timeEnd('a');
console.time('b');
for(var i = 0;i<10;i++){
  (function(i){
    setTimeout(function(){
      console.log(i);  
    },1000);
  })(i)
}
console.timeEnd('b');
console.time('c');
for(var i = 0;i<10;i++){
  let a = i;
  let p = new Promise((resolve,reject)=>{
    setTimeout(()=>{resolve(a)},1000);
  });
  p.then(i=>console.log(i))
}
console.timeEnd('c');

效率上,我在目前新版chrome的執行結果以下:get

a: 0.35009765625ms
b: 0.348876953125ms
c: 0.880126953125ms

注意:可能不一樣系統不一樣環境的執行結果不同。因此,有時候極客玩玩就是了,認真你就輸啦-.-

總結

之前我偏執的認爲,能作出東西就好了。基礎不重要。因此我老是一隻停留在作東西的階段。可是後來反過來想:假設你想買車,那麼你會選一個對汽車參數很熟的銷售員仍是選擇一個你問什麼問題他都說查查再回答你的銷售員呢?答案是確定的。因此說,可能公司招人也同樣吧。

可是,這些問題真的有用嗎?沒錯,我都有不少問題沒回答好,若是是爲了準備一次很nice的面試,我大能夠特地的多跑幾家,而後把遇到的有問題的面試題都總結下來。不會的再去查詢,我想翻來覆去也沒多少基礎可問吧?就像找個美工就問:你會切圖嘛?這些稍微花點時間都能學會的問題。我的以爲沒特別大的意義。

(本文摘取自個人博客:http://79px.com/blog/57cd347b...

相關文章
相關標籤/搜索