前言
题目来自Daily-Interview-Question 木易杨
欢迎star,加入讨论
本文记录自己对题目的解决方式以及综合大神们的看法。
题目
1、修改以下 print 函数,使之输出 0 到 99,或者 99 到 0
要求:
1、只能修改 setTimeout 到 Math.floor(Math.random() * 1000 的代码
2、不能修改 Math.floor(Math.random() * 1000
3、不能使用全局变量
function print(n){
setTimeout(() => {
console.log(n)
}, Math.floor(Math.random() * 1000))
}
for(var i = 0; i < 100; i++){
print(i)
}
答案:
修改以下 print 函数,使之输出 0 到 99,或者 99 到 0
这道题打乱了输出顺序,根本解决办法就是让定时器里的函数在同一任务队列里去执行。
考察setTimeout函数以及对闭包的理解。
答案一:
momodiy首先给出了解法
function print(n){
setTimeout((() => {
console.log(n)
return ()=>{}
}).call(n,[]), Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
print(i);
}
这个方法暂时没看懂
答案二:
ryanZiegler利用了setTimeout函数的参数值,给出了答案
文章末尾会有setTimeout函数的介绍。
function print(n){
setTimeout(() => {
console.log(n);
}, 1, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
print(i);
}
答案三:
dorseysen 和 defypro用立即执行函数解决了这个问题
function print(n){
setTimeout( (() => {
console.log(n);
return ()=>{};
})(), Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++) {
print(i);
}
答案四:
dorseysen根据setTimeout的时间戳给出了答案
function print(n){
setTimeout(() => {
setTimeout( () =>{
console.log(n);
}, 1000 * n)
}, Math.floor(Math.random() * 1000))
}
for(var i = 0; i < 100; i++){
print(i)
}
答案五:
dreamsk直接利用表达式给出了答案
function print(n){
setTimeout(console.log(n), Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++) {
print(i);
}
答案六:
ByeWord 利用var定义的变量i
for 语句块 var 声明变量存在于外部作用域中,setTimeout 的回调可直接引用 变量 i
function print (n) {
setTimeout(() => {
console.log(i--)
}, Math.floor(Math.random() * 1000))
}
for(var i = 0; i < 100; i++){
print(i)
}
答案七:
zhangxiangliang 注释法
function print(n){
// setTimeout(() => {
console.log(n);
//}, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
print(i);
}
扩展:
之前有写过关于闭包的题
在 JS 中,闭包存在的意义就是让我们可以间接访问函数内部的变量。
题目:
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)
}
这道题的输出是输出5个6
首先因为 setTimeout 是个异步函数,所以会先把循环全部执行完毕,这时候 i 就是 6 了,所以会输出一堆 6。
如果要输出正确顺序的结果:
解决方法一:闭包
for (var i = 1; i <= 5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j)
}, j * 1000)
})(i)
}
在上述代码中,我们首先使用了立即执行函数将i
传入函数内部,这个时候值就被固定在了参数j
上面不会改变,当下次执行 timer
这个闭包的时候,就可以使用外部函数的变量 j
,从而达到目的。
解决方法二:使用 setTimeout
的第三个参数
for (var i = 1; i <= 5; i++) {
setTimeout(
function timer(i) {
console.log(i)
},i * 1000, i
)
}
解决方法三:使用let
定义 i
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)
}
setTimeout函数说明链接:setTimeout MDN