Skip to content

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

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

let

信息

利用 let 变量的特性 — 在每一次 for 循环的过程中,let 声明的变量会在当前的块级作用域里面(for 循环的 body 体,也即两个花括号之间的内容区域)创建一个文法环境(Lexical Environment),该环境里面包括了当前 for 循环过程中的 i

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

IIFE 立即执行函数

信息

利用函数自执行的方式,把当前 for 循环过程中的 i 传递进去,构建出块级作用域。

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

setTimeout

信息

setTimeout 函数的第三个参数,会作为回调函数的第一个参数传入

  1. 代码 1:
js
for (var i = 0; i < 10; i++) {
  setTimeout(
    (i) => {
      console.log(i);
    },
    1000,
    i
  );
}
  1. 代码 2:
js
for (var i = 0; i < 10; i++) {
  setTimeout(console.log, 1000, i);
}
  1. 代码 3:
js
for (var i = 0; i < 10; i++) {
  setTimeout(
    (() => {
      console.log(i);
    })(),
    1000
  );
}
  1. 代码 4:
js
for (var i = 0; i < 10; i++) {
  setTimeout(
    ((j) => {
      console.log(j);
    })(i),
    1000
  );
}
  1. 代码 5:
js
for (var i = 0; i < 10; i++) {
  setTimeout(
    ((j) => {
      console.log(j);
    }).call(Object.create(null), i),
    1000
  );
}
  1. 代码 6:
js
for (var i = 0; i < 10; i++) {
  setTimeout(
    ((j) => {
      console.log(j);
    }).apply(Object.create(null), [i]),
    1000
  );
}

bind 特性

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

try catch 块级作用域

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

eval 和 new Function

信息

利用 eval 或者 new Function 执行字符串

  1. 代码 1:
js
for (var i = 0; i < 10; i++) {
  setTimeout(eval("console.log(i)"), 1000);
}
  1. 代码 2:
js
for (var i = 0; i < 10; i++) {
  setTimeout(new Function("console.log(i)")(), 1000);
}
  1. 代码 3:
js
for (var i = 0; i < 10; i++) {
  setTimeout(new Function("j", "console.log(j)")(i), 1000);
}