一个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...

相关文章
相关标签/搜索