前端100问

【前端100问】Q31:改造下面的代码,使之输出 0 - 9,写

2020-12-27  本文已影响0人  alanwhy

写在前面

此系列来源于开源项目:前端 100 问:能搞懂 80%的请把简历给我
为了备战 2021 春招
每天一题,督促自己
从多方面多角度总结答案,丰富知识
改造下面的代码,使之输出 0 - 9,写出你能想到的所有解法。
简书整合地址:前端 100 问

题目

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

正文回答

方法一

原理:

// setTimeout(function, milliseconds, param1, param2, ...)
// function 必需。要调用一个代码串,也可以是一个函数。
// milliseconds 可选。执行或调用 code/function 需要等待的时间,以毫秒计。默认为 0。
// 可选。 传给执行函数的其他参数(IE9 及其更早版本不支持该参数)。
for (var i = 0; i < 10; i++) {
  setTimeout(
    (i) => {
      console.log(i);
    },
    1000,
    i
  );
}

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

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

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

for (let i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
// 等价于
for (let i = 0; i < 10; i++) {
  let _i = i; // const _i = i;
  setTimeout(() => {
    console.log(_i);
  }, 1000);
}
方法三

利用函数自执行的方式,把当前 for 循环过程中的 i 传递进去,构建出块级作用域。IIFE 其实并不属于闭包的范畴。

利用其它方式构建出块级作用域

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

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

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

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

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

for (var i = 0; i < 10; i++) {
  setTimeout(new Function("console.log(i)")(), 1000);
}
上一篇下一篇

猜你喜欢

热点阅读