改造下面的代码,使之输出0 - 9,写出你能想到的所有解法。

321 阅读2分钟
for (var i = 0; i< 10; i++){
	setTimeout(() => {
		console.log(i);
    }, 1000)
}

1、

原理:

利用 setTimeout 函数的第三个参数,会作为回调函数的第一个参数传入 利用 bind 函数部分执行的特性 代码 1:

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

代码 2:

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

代码 3:

for (var i = 0; i < 10; i++) {
  setTimeout(console.log.bind(Object.create(null), i), 1000)
}

2、

原理:

构建出块级作用域。

代码 1:

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

代码 2:

for (var i = 0; i < 10; i++) {
  try {
    throw new Error(i);
  } catch ({
    message: i
  }) {
    setTimeout(() => {
      console.log(i);
    }, 1000)
  }
}

代码 3:

for(var i = 0; i < 10; i++){ 
  try{
     throw i;
  }catch(i){
     setTimeout(() => { console.log(i); },1000)    
  }
} 

3、

原理:

很多其它的方案只是把 console.log(i) 放到一个函数里面,因为 setTimeout 函数的第一个参数只接受函数以及字符串,如果是 js 语句的话,js 引擎应该会自动在该语句外面包裹一层函数

代码 1:

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

代码 2:

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

代码 3:

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

代码 4:

for (var i = 0; i < 10; i++) {
  setTimeout((i => {
    console.log(i);
  }).call(Object.create(null), i), 1000)
}

代码 5:

for (var i = 0; i < 10; i++) {
  setTimeout((i => {
    console.log(i);
  }).apply(Object.create(null), [i]), 1000)
}

代码 6:

for (var i = 0; i < 10; i++) {
  setTimeout((i => {
    console.log(i);
  }).apply(Object.create(null), { length: 1, '0': i }), 1000)
}

4、

原理:

利用 eval 或者 new Function 执行字符串,然后执行过程同方法四

代码 1:

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

代码 2:

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

代码 3:

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