关于Javascript很经典的闭包问题与异步问题,希望你能仔细阅读相关内容
问题一 请说明其输出结果
for(var i = 0; i < 5; i++) {
setTimeout(function() {
console.log("inner", new Date().getTime(), i);
}, 1000);
}
console.log("outer", new Date().getTime(), i);
这个很明显可以看出,上面的代码的for循环中存在着异步代码,先执行的是同步代码,之后才执行异步代码,所以结果也不难猜想,至于利用Date,只是希望看到它们的执行次序与间隔时间,因为定时器本身也会被延迟
outer 1501927632188 5
inner 1501927633189 5
inner 1501927633190 5
inner 1501927633192 5
inner 1501927633193 5
inner 1501927633194 5
问题二 在问题一的基础上,用“->”表示其前后的两次输出之间有 1 秒的时间间隔,而”,”表示其前后的两次输出之间的时间间隔可以忽略,代码是怎样的?
for(var i = 0; i < 5; i++) {
var first = 0;
setTimeout(function() {
if(first > 0) {
console.log(',' + i);
}else {
console.log(i);
}
first++;
}, 1000);
}
console.log('->' + i);
问题三 对问题一种的代码进行修改,使得其能输出5 0 1 2 3 4
,写出相应的代码
方法一 立即执行函数
for(var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 1000);
})(i);
}
console.log(i);
方法二 函数传参
var fun = function(i) {
setTimeout(function() {
console.log(i);
}, 1000);
}
for(var i = 0; i < 5; i++) {
fun(i);
}
console.log(i);
方法三 let的使用
for(let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
console.log(i);
问题四:如何输出0 1 2 3 4 5
,请写出代码?
方法一 自执行函数 + 定时器
for(var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, j * 1000);
})(i);
}
setTimeout(function() {
console.log(i);
}, 1000 * i);
对于上面的代码,我也尝试不利用j * 1000
,尝试多次之后,也是按照0 1 2 3 4 5
的结果输出的,但是定时器触发时机有可能是不确定的,所以还是加上吧
方法二 Promise
Promise是ES6中的内容,可以参考这篇博客,下面我们就用Promise来解决这个问题
var arys = [];
for(var i = 0; i < 5; i++) {
((j) => {
var e = new Promise(function(resolve) {
setTimeout(() => {
console.log(j);
}, 1000);
resolve();
});
arys.push(e);
})(i);
}
Promise.all(arys).then(()=> {
setTimeout(function() {
console.log(i);
}, 1000);
});
方法三 async与await
const sleep = () => new Promise((resolve) => {
setTimeout(resolve, 1000);
});
(async () => {
for (var i = 0; i < 5; i++) {
await sleep(1000);
console.log(i);
}
await sleep();
console.log(i);
})();
本文牵扯到的关键点就是,闭包、立即执行函数、Promise、async/await,希望你有所收获