【前端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
函数的第三个参数,会作为回调函数的第一个参数传入 - 利用
bind
函数部分执行的特性
// 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);
}