题目:让console.log输出1,2,3,4,5,6......
for (var i = 0; i< 10; i++){
    setTimeout(() => {
        console.log(i);
    }, 1000)
}
当前输出10,10,10.....(共十个),因为setTimeout是异步任务,会首先执行主任务。再执行异步任务。而i是全局变量。所以等异步任务执行的时候,i一直都是10;
方法一
使用let,let是区块变量,只能在大括号内有效,并不会向后传递。
for (let i = 0; i< 10; i++){
    setTimeout(() => {
        console.log(i);
    }, 1000)
}
方法二
自执行函数 把当前 for 循环过程中的 i 传递进去,构建出块级作用域
for (var i = 0; i< 10; i++){
       (function(i){
           setTimeout(() => {console.log(i); }, 1000)
        })(i)
}
方法三
利用 setTimeout 函数的第三个参数,会作为回调函数的第一个参数传入
for (var i = 0; i< 10; i++){
  setTimeout(((i) => {
    console.log(i);
    })(i), 1000)
}
//或者  
 for (var i = 0; i < 10; i++) {
  setTimeout(console.log, 1000, i)
}
方法四
利用try catch
for(var i = 0; i < 10; i++){ 
  try{
     throw i;
  }catch(i){
     setTimeout(() => { console.log(i); },1000)    
  }
} 
方法五:promise
for (var i = 0; i < 10; i++) {
    timeoutPromise(i);
}
function timeoutPromise(i) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(i);
            resolve(true);
        }, 1000);
    });
}
方法六:generator函数
for (var i = 0; i < 10; i++) {
    timeoutGenerator(i).next();
}
function* timeoutGenerator (i) {
    yield setTimeout(() => {
        console.log(i);
    }, 1000);
}
方法七:await async
async function init () {
    for (var i = 0; i < 10; i++) {
        await timeoutPromise(i);
    }    
}
function timeoutPromise (i) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(i);
            resolve(true);
        }, 1000);   
    });
}
init();










