前言
最常考的面试题!别再答不上来了,丢人丢到家了!
在面试之前,我就看到过这道题,但是没有仔细研究,到了面试时人家真的问了,我当时悔之晚矣,呜呜呜~,所以没搞懂的小伙伴快看看吧!
面试官:代码输出什么?
for (var i = 0; i < 5; i++) {
setTimeout(function timer() {
console.log(i)
}, 1000)
}
// 1s后一起输出5个5
console.log(i) // 5
复制代码
为啥子嘞?为什么不是5个4呀?
首先变量 i 由var声明,这个变量就是全局变量,每次循环后都覆盖原来的i。由于js的事件循环机制,先执行完for后再执行的setTimeout,所以setTimeout在1s后输出5个5
面试官:如果setTimeout中的1000变为0呢?
for (var i = 0; i < 5; i++) {
setTimeout(function timer() {
console.log(i)
}, 1000)
}
// 立刻输出5个5
复制代码
面试官:怎么让他输出0,1,2,3,4
方法一:立即执行函数
for (var i = 0; i < 5; i++) {
((j) => {
setTimeout(() => {
console.log(j)
}, j * 1000)
})(i)
}
复制代码
转换成函数调用形式
for (var i = 0; i < 5; i++) {
function run(j) {
setTimeout(() => {
console.log(j)
}, 1000)
}
run(i)
}
复制代码
使用立即执行函数将i传入函数内部,此时i的值固定在了j上,那么我们再执行循环的时候就变成了run(0)、run(1) … run(4),所以最后输出0,1,2,3,4
方法二:let
for (let i = 0; i < 5; i++) {
setTimeout(()=> {
console.log(i)
}, i * 1000)
}
复制代码
使用let声明会触发块级作用域,所以会生成0,1,2,3,4
方法三:使用setTimeout的第三个参数
for (var i = 0; i < 5; i++) {
setTimeout((j) => {
console.log(j)
},
i * 1000,
i)
}
复制代码
没想到setTimeout还有第三个参数,我也很惊讶!那就来仔细的了解下setTimeout的参数吧!
setTimeout的三个参数
setTimeout(function, delay, arg1, ..., argN)
复制代码
function
到期时间之后执行的函数
delay
延迟的毫秒数(一秒等于1000毫秒)函数的调用会在该延迟之后发生。如果省略该参数,delay取默认值0,意味着“马上”执行,或者尽快执行。不管是哪种情况,实际的延迟时间可能会比期待的(delay毫秒数) 值长,原因请查看实际延时比设定值更久的原因:最小延迟时间。
arg1, ..., argN
附加参数,一旦定时器到期,他们会作为参数传递给function
结语
这道题考查差JS的基础知识:内存空间,执行上下文,变量对象,作用域,闭包,setTimeout定时器,真的很考验对JS基础的掌握程度。继续加油吧!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END