Github每日一题——7.17学习记录

前言


题目来自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

你可能感兴趣的:(Github每日一题——7.17学习记录)