关于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,希望你有所收获