第 31 题:改造下面的代码,使之输出0 - 9,写出你能想到的所有解法。
zpzxgcr opened this issue · 66 comments
for (var i = 0; i< 10; i++){
setTimeout((i) => {
console.log(i);
}, 1000,i)
}
// 解法一: for (let i = 0; i< 10; i++){ setTimeout(() => { console.log(i); }, 1000) }// 解法二: for (var i = 0; i< 10; i++){ ((i) => { setTimeout(() => { console.log(i); }, 1000) })(i) }
for (var i = 0; i< 10; i++){
setTimeout(((i) => {
console.log(i);
})(i), 1000)
}
for (var i = 0; i< 10; i++){
setTimeout((() => {
console.log(i);
})(), 1000)
}
for (let i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
}
正常写法:
for (var i = 0; i < 10; i++) {
setTimeout(((i) => {
console.log(i);
})(i), 1000)
}
砸场子写法:
let i = 0,
timer = setInterval(() => {
i < 10 ?
console.log(i++) :
clearInterval(timer);
})
for(let i = 0 ; i < 10; i++){
setTimeout(()=>{
console.log(i)
},1000)
}
for(var i = 0 ; i < 10 ; i++){
(function(i){
setTimeout(()=>{
console.log(i)
},1000)
}(i))
}
解决办法汇总
-
方法一
原理:
- 利用
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) }
- 利用
-
方法二
原理:
- 利用
let
变量的特性 — 在每一次for
循环的过程中,let
声明的变量会在当前的块级作用域里面(for
循环的 body 体,也即两个花括号之间的内容区域)创建一个文法环境(Lexical Environment),该环境里面包括了当前for
循环过程中的i
,具体链接
代码 1:
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 其实并不属于闭包的范畴。参考链接如下:
- 利用其它方式构建出块级作用域
代码 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) } }
-
方法四
原理:
- 很多其它的方案只是把
console.log(i)
放到一个函数里面,因为setTimeout
函数的第一个参数只接受函数以及字符串,如果是js
语句的话,js
引擎应该会自动在该语句外面包裹一层函数
代码 1:
for (var i = 0; i < 10; i++) { setTimeout(console.log(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) }
- 很多其它的方案只是把
-
方法五
原理:
- 利用 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) }
利用try/catch的块级作用域也能实现目的:
for(var i = 0; i < 10; i++){
try{
throw i;
}catch(i){
setTimeout(() => { console.log(i); },1000)
}
}
闭包解法
setTimeout(() => {
for (var i = 0; i< 10; i++){
console.log(i);}
}, 1000);
for (var i = 0; i< 10; i++){ setTimeout((i) => { console.log(i); }, 1000,i) }
除了 let 这个可能是改动最少的😂
for (var i = 0; i< 10; i++){
(() => {
var temp = i // 闭包
setTimeout(() => {
console.log(temp);
}, 1000)
})()
}
利用try/catch的块级作用域也能实现目的:
for(var i = 0; i < 10; i++){ try{ throw i; }catch(i){ setTimeout(() => { console.log(i); },1000) } }
涨知识啦
for(let i=0;i<10;i++){
setTimeout(() => {
console.log(i);
}, 1000);
}
for(var i=0;i<10;i++){
(
function(){
var j = i;
setTimeout((()=>{
console.log(j)
}),1000)
}
)()
}
for(var i=0;i<10;i++){
(function(i){
setTimeout((()=>{
console.log(i)
}),1000)
})(i)
}
for (var i = 0; i< 10; i++){
setTimeout(((i) => {
console.log(i);
}).call(null,i), 1000)
}
最简单的将var改成let
for (let i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
}
其实有些方法是不满足要求的,为啥这样说呢?因为题目其实是有隐性要求,也即每隔 1s 输出一个数字,虽说题目没有明确说出来。所以这种解法不满足要求,比如:
for (var i = 0; i < 10; i++) {
setTimeout(console.log(i, Date.now()), 1000)
}
for (let i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
}
for (var i = 0; i< 10; i++){
(function(i){
setTimeout(() => {
console.log(i);
}, 1000)
})(i)
}
for (var i = 0; i < 10; i++) { console.log(i) }
// 1 使用es5 块级作用域 let
for (let i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
}
// 2 闭包法
for (var i = 0; i< 10; i++){
(function(i) {
setTimeout(() => {
console.log(i);
}, 1000)
})(i)
}
// 3 promise
for (var i = 0; i< 10; i++){
new Promise((r,ej) => ej(i)).catch(i => setTimeout(() => {
console.log(i);
}, 1000))
}
// 4 let 临时变量
for (var i = 0; i< 10; i++){
let _i = i;
setTimeout(() => {
console.log(_i);
}, 1000)
}
// 5 setTimeout传参
for (var i = 0; i< 10; i++){
setTimeout(i => {
console.log(i);
}, 1000, i)
}
// 6 try catch法
for (var i = 0; i< 10; i++){
try {
throw i;
} catch (i) {
setTimeout(() => {
console.log(i);
}, 1000)
}
}
// 解法1 利用setTimeout的第三个参数
for (var i = 0; i < 10; i++) {
setTimeout( function timer(param){
console.log(param);
},1000, i);
}
// 解法2 用立即执行函数和闭包构建一个单独作用域
for (var i = 0; i < 10; i++) {
(function(i){
setTimeout( function (){
console.log(i);
},1000);
})(i);
}
// 解法3 利用let构造块级作用域
for (let i = 0; i < 10; i++) {
setTimeout( function (){
console.log(i);
},1000);
}
// 解法4 利用promise包装setTimeout
for (var i = 0; i < 10; i++) {
timeoutPromise(i);
}
function timeoutPromise(i) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(i);
resolve(true);
}, 1000);
});
}
// 解法5 用generator函数
for (var i = 0; i < 10; i++) {
timeoutGenerator(i).next();
}
function* timeoutGenerator (i) {
yield setTimeout(() => {
console.log(i);
}, 1000);
}
// 解法6 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();
// 原题
for (var i = 0; i < 10; i++) {
setTimeout( function (){
console.log(i);
},1000);
}
for(var i = 0; i < 10; i++){
(function(){
console.log(i)
})()
}
console.log(0),console.log(1),console.log(2),console.log(3),console.log(4),console.log(5),console.log(6),console.log(7),console.log(8),console.log(9)
for (var i = 0; i< 10; i++){
console.log(i);
}
没有人这么写吗?不要打我啊
for (let i = 0; i< 10; i++){
console.log(i);
}
又没说一定要用setTimeOut,这难道不是最简单效率最高的一种解法?
1、闭包实现 变量保存,settimeout第三个参数转为函数参数也属于闭包。
2、let创建作用域,实现类似闭包的效果,变量保存
总结,学好闭包就可以了,作用域解决一切花里胡哨
for (var i = 0; i< 10; i++){ setTimeout((i) => { console.log(i); }, 1000,i) }除了 let 这个可能是改动最少的
这两种解法,都好牛B
看到最后没有看到有人写一秒输出一个的情况。
一秒输出一个数字只需要在定时器后面乘以i即可,
setTimeout第一个参数是立即执行的函数除外。
方法1:立即执行函数表达式法简称(IIFE)不标准叫法立即执行函数
for (var i = 0; i<10; i++) {
// IIFE: (function (j) {})(i);
(function (j) {
setTimeout(function () {
console.log(j)
}, 1000)
})(i)
}
方法2:将var 改为 let
for (let i = 0; i<10; i++) {
setTimeout(function () {
console.log(i)
}, 1000)
}
方法3:使用promise函数
for (var i = 0; i<10; i++) {
new Promise(function (resolve, reject) {
resolve(i)
}).then(function (data) {
setTimeout(() => {
console.log(data)
}, 1000)
})
}
方法4:使用bind绑定(参考楼上的,加深印象)
for(var i = 0; i<10; i++) {
setTimeout(console.log.bind(null, i), 1000)
}
方法5: 使用try catch构成块级作用域(参考楼上的,加深印象)
for (var i = 0; i<10; i++) {
try{
throw(i)
}catch (i) {
setTimeout(function () {
console.log(i)
},1000)
}
}
另附promise相关的题目
for (var i = 0; i< 10; i++){
setTimeout((i) => {
console.log(i);
}, 1000, i)
}
利用const/let的块级作用域
for (var i = 0; i< 10; i++){
{
const j=i;
setTimeout(() => {
console.log(j);
}, 1000)
}
}
下面这个比较奇葩,看到大佬的cath语句块延长作用域链,就想到了with。
for (var i = 0; i< 10; i++){
with(new Number(i)){
setTimeout(() => {
console.log(valueOf());
}, 1000)
}
}
压根就不需要改
压根就不需要改
不改i一直++,打印出10.。。你自己试试
// 闭包
for (var i = 0; i < 10; i++) {
(function (i){
setTimeout(() => {
console.log(i);
}, 1000);
})(i);
}
// 块作用域
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
// timeout 传参
for (var i = 0; i < 10; i++) {
setTimeout((i) => {
console.log(i);
}, 1000, i);
}
题目的意思应该是打印出0-9,并且使每隔1S打印出一个吧。不然setTimeout的意义在哪。直接for(var i=0;i<10;i++)(console.log(i))好了。所以每一个方法上都应该把定时器的时间 *i 吧
解决办法汇总
方法一
原理:
- 利用
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) }方法二
原理:
- 利用
let
变量的特性 — 在每一次for
循环的过程中,let
声明的变量会在当前的块级作用域里面(for
循环的 body 体,也即两个花括号之间的内容区域)创建一个文法环境(Lexical Environment),该环境里面包括了当前for
循环过程中的i
,具体链接代码 1:
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 其实并不属于闭包的范畴。参考链接如下:
利用其它方式构建出块级作用域
代码 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) } }方法四
原理:
- 很多其它的方案只是把
console.log(i)
放到一个函数里面,因为setTimeout
函数的第一个参数只接受函数以及字符串,如果是js
语句的话,js
引擎应该会自动在该语句外面包裹一层函数代码 1:
for (var i = 0; i < 10; i++) { setTimeout(console.log(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) }方法五
原理:
- 利用 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) }
看了很多,我再加一个吧
for (var i = 0; i < 10; i++) {
console.log(i)
}
解决办法汇总
方法一
原理:
- 利用
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) }方法二
原理:
- 利用
let
变量的特性 — 在每一次for
循环的过程中,let
声明的变量会在当前的块级作用域里面(for
循环的 body 体,也即两个花括号之间的内容区域)创建一个文法环境(Lexical Environment),该环境里面包括了当前for
循环过程中的i
,具体链接代码 1:
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 其实并不属于闭包的范畴。参考链接如下:
利用其它方式构建出块级作用域
代码 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) } }方法四
原理:
- 很多其它的方案只是把
console.log(i)
放到一个函数里面,因为setTimeout
函数的第一个参数只接受函数以及字符串,如果是js
语句的话,js
引擎应该会自动在该语句外面包裹一层函数代码 1:
for (var i = 0; i < 10; i++) { setTimeout(console.log(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) }方法五
原理:
- 利用 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) }
经过测试,我这边直接在settimeout里的第一个参数修改成js语句会报错:
0
timers.js:118
throw new ERR_INVALID_CALLBACK(callback);
^
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received undefined
at setTimeout (timers.js:118:11)
function* delay(i){
yield setTimeout(() => {
console.log(i)
},1000*i)
}
for (var j =0 ; j< 10; j++){
delay(j).next()
}
for (var i = 0; i< 10; i++) {
setTimeout(() => {
console.log(i);
}, 1000)
}
for (var i = 0; i< 10; i++){
setTimeout((i) => {
console.log(i);
}, 1000,i)
}
for (var i = 0; i< 10; i++){
((i) => {
setTimeout(() => {
console.log(i);
}, 1000)
})(i)
}
for (let i = 0; i< 10; i++){ setTimeout(() => { console.log(i); }, 1000) }
大智若愚
for (var i = 0; i < 10; i++) {
console.log(i)
}
方式一
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, 1000 * i);
}
方式二
for (var i = 0; i < 10; i++) {
(function (j) {
setTimeout(() => {
console.log(j);
}, 1000 * j);
})(i);
}
方式三
for (let i = 0; i < 10; i++) {
setTimeout((i) => {
console.log(i);
}, 1000 * i, i);
}
方式四
let i = 0;
const timer = setInterval(() => {
console.log(i);
i++;
if (i > 9) {
clearInterval(timer);
}
}, 1000);
解决办法汇总
方法一
原理:
- 利用
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) }方法二
原理:
- 利用
let
变量的特性 — 在每一次for
循环的过程中,let
声明的变量会在当前的块级作用域里面(for
循环的 body 体,也即两个花括号之间的内容区域)创建一个文法环境(Lexical Environment),该环境里面包括了当前for
循环过程中的i
,具体链接代码 1:
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 其实并不属于闭包的范畴。参考链接如下:
利用其它方式构建出块级作用域
代码 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) } }方法四
原理:
- 很多其它的方案只是把
console.log(i)
放到一个函数里面,因为setTimeout
函数的第一个参数只接受函数以及字符串,如果是js
语句的话,js
引擎应该会自动在该语句外面包裹一层函数代码 1:
for (var i = 0; i < 10; i++) { setTimeout(console.log(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) }方法五
原理:
- 利用 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) }
感觉就是两种方法:
- 将变化的数值的每一个瞬间当参数传入函数
- 块级作用域
### 第一种 var -> let
### 第二种 settimeout绑定参数,回调传参
setTimeout((i) => {
console.log(i);
}, 1000,i)
### 第三种 使用外部变量保存每一次的i
let j = i;
setTimeout(() => {
console.log(j);
}, 1000)
### 第四种立即执行函数传参i或者回调函数包裹立即执行函数
((i)=>setTimeout(() => {
console.log(i);
}, 1000))(i)
setTimeout(((i) => {
console.log(i);
})(i), 1000)
### 第五种bind或者call或者apply 也是为了传参 把每一次的i绑定
setTimeout(((i) => {
console.log(i);
}).call({},i), 1000)
// let 块级作用域
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, 1000)
}
// 闭包
for (var i = 0; i < 10; i++) {
((j) => {
setTimeout(() => {
console.log(j);
}, 1000)
})(i)
}
// promise 异步,其实也可以用generator将i保存在堆中
for (var i = 0; i < 10; i++) {
new Promise((resolved, rejected) => {
resolved(i);
}).then((j) => {
setTimeout(() => {
console.log(j);
}, 1000)
})
}
// try catch
for (var i = 0; i < 10; i++) {
try {
throw (i);
} catch (i) {
setTimeout(() => {
console.log(i);
}, 1000)
}
}
//来一个没提到的
function go(i){
setTimeout(()=>{
console.log(i)
}, 1000*i)
}
for(var i = 0; i < 10; i++){
go(i);
}
console.log(...[0,1,2,3,4,5,6,7,8,9])
// 方法1
for (var i = 0; i< 10; i++){
(function fn(i){
setTimeout(() => {
console.log(i);
}, 1000)
})(i)
}
// 方法2
for (var i = 0; i< 10; i++){
let y = i
setTimeout(() => {
console.log(y);
}, 1000)
}
// 方法3
for (let i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
}
console.log(...[0,1,2,3,4,5,6,7,8,9])
are you dou 我?
for (var i = 0; i< 10; i++){
setTimeout(console.log, 1000, i)
}
这是最简单的!
// 1. 通过立即执行函数,保存每一次遍历的i
// 相当于生成了 10个立即执行函数
for (var i = 0; i < 10; i++) {
(function (i) {
setTimeout(() => {
console.log(i);
}, 0);
})(i);
}
// 2. 使用let 生成 块级作用域
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
// 创建函数 通过函数的入参生成新的变量-----
for (var i = 0; i < 10; i++) {
function name(i) {
setTimeout(() => {
console.log(i)
}, 1000)
}
name(i)
}
为啥没人写这个 而且 闭包能 解决这道题的原因该是因为函数的入参 生成的变量保留了i 而不是闭包的问题
- 解法1 将var 改为 let
{
for (let i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
}
}
- 解法二 利用 setTimeout 第三个参数
{
for (var i = 0; i< 10; i++){
setTimeout((j) => {
console.log(j);
}, 1000, i)
}
}
- 解法三 利用闭包
{
for (var i = 0; i< 10; i++){
(
function (j) {
setTimeout(() => {
console.log(j);
}, 1000);
}
)(i)
}
}
我用 es6 实现一下
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
async function fn() {
for (var i = 0; i < 10; i++){
await sleep(1000);
console.log(i);
}
}
fn();
for (var i = 0; i < 10; i++) {
Promise.resolve(i).then((i)=>{
setTimeout(() => {
console.log(i)
}, 1000);
})
}
for (var i = 0; i < 5; i++) {
setTimeout(function (i) {
console.log(i);
}.bind(undefined, i), 1000);
}
for (var i = 0; i < 10; i++) {
(function () {
var j = i;
setTimeout(() => {
console.log(j);
}, 0);
})();
}
// 1、let
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i)
}, 1000)
}
// 2、setTimeout 的第三个参数
for (var i = 0; i < 10; i++) {
setTimeout(
(a) => {
console.log(a)
},
1000,
i
)
}
// 3、IIFE
for (var i = 0; i < 10; i++) {
;(function (a) {
setTimeout(() => {
console.log(a)
}, 1000)
})(i)
}
// 4、try catch 块级作用域
for (var i = 0; i < 10; i++) {
try {
throw i
} catch (e) {
setTimeout(() => {
console.log(e)
}, 1000)
}
}
// 5、bind
for (var i = 0; i < 10; i++) {
setTimeout(((i) => {
console.log(i)
}).bind(null, i), 1000)
}
- JavaScript引擎执行机制?
- 放入异步任务队列的时机很重要!
- 理解作用域
- let在 for 循环的作用域在花括号内
- 闭包或箭头函数,他们在干什么?
for (var i = 0; i < 10; i++) {
(function(j){//闭包
setTimeout(function(){
console.log(j);//分别输出i的值
},1000*j) //设置明显的时间差
})(i);//闭包
};
理解到考点,背解意义不大。
for (var i = 0; i < 10; i++) { ( function(i) { setTimeout(() => { console.log(i); }, 1000) } )(i); };
for (var i = 0; i < 10; i++) { setTimeout((i) => { console.log(i); }, 1000,i) };
兄弟们,给你们来个邪门歪道
for (var i = 0; i< 10; i++){
setTimeout(() => {
console.log(0-(i--)+10);
}, 1000)
}
优秀,第三个参数可否解释下
//方法一
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i)
}, 1000)
}
//方法二
for (var i = 0; i < 10; i++) {
(function(j) {
setTimeout(() => {
console.log(j)
}, 1000)
})(i)
}
//方法三
for (var i = 0; i < 10; i++) {
foo(i)
}
function foo(i) {
setTimeout(() => {
console.log(i)
}, 1000)
}
//方法四
for (var i = 0; i < 10; i++) {
setTimeout((j) => {
console.log(j)
}, 1000, i)
}
//方法五
for (var i = 0; i < 10; i++) {
new Promise(function(resolve, reject) {
resolve(i)
}).then(function(i) {
setTimeout(() => {
console.log(i)
}, 1000)
})
}
都不运行一下的吗
正常写法:
for (var i = 0; i < 10; i++) { setTimeout(((i) => { console.log(i); })(i), 1000) }砸场子写法:
let i = 0, timer = setInterval(() => { i < 10 ? console.log(i++) : clearInterval(timer); })
牛逼
在原始代码中,由于 setTimeout 回调函数是在循环结束后才执行,所以无论循环多快,输出的结果都会是 10 个 10。为了实现按顺序输出 0 - 9,可以尝试以下几种解法:
解法一:使用 let 关键字声明循环变量
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i);
}, 1000);
}
解法二:使用闭包保存变量
for (var i = 0; i < 10; i++) {
(function (j) {
setTimeout(() => {
console.log(j);
}, 1000);
})(i);
}
解法三:使用 setTimeout 的第三个参数传递当前循环的索引
for (var i = 0; i < 10; i++) {
setTimeout((j) => {
console.log(j);
}, 1000, i);
}
解法四:使用 async/await 和 Promise
function delayLog(i) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(i);
resolve();
}, 1000);
});
}
async function printNumbers() {
for (var i = 0; i < 10; i++) {
await delayLog(i);
}
}
printNumbers();
解法一
for (let i = 0; i < 10; i++) `{`
`console.log(i)`
}
解法二
for (var i = 0; i < 10; i++) {
setTimeout((a) => {
console.log(a)
}, 1000,i)
}
解法三
for (var i = 0; i < 10; i++) {
new Promise((resolve) => {
resolve(i)
}).then((res) => {
setTimeout(() => {
console.log(res)
}, 1000)
})
}