【问题标题】:Recursive function solving递归函数求解
【发布时间】:2021-04-30 12:47:44
【问题描述】:

不知道为什么在运行时它会同时打印数组中的两个点。为什么它不打印点暂停然后打印破折号然后点。我的条件写错了吗?

function morseCode(code) {
  if (code.length === 0) {
    return;
  }
  let ele = code[code.length - 1];
  if (ele === "dot") {
    setTimeout(() => {
      console.log("dot");
    }, 100);
  } else {
    setTimeout(() => {
      console.log("dash");
    }, 300);
  }
  return morseCode(code.slice(0, -1));
}
let code = ["dot", "dash", "dot"];

morseCode(code);
// print 'dot'
// pause for 100ms
// print 'dash'
// pause for 300ms
// print 'dot'
// pause for 100ms

【问题讨论】:

  • 你已经基本同时设置了三个定时器,两个100ms,一个300ms,所以两个100ms定时器(点)完成并打印,100ms后300ms定时器完成。如果你想暂停,你需要调用morseCode(),并在定时器内部使用切片数组。
  • setTimeout 不会“暂停”代码执行。它的作用是......它将您传递给它的函数推入“堆栈”,并给出超时值。然后,一旦您的函数完成运行,浏览器将转到此“堆栈”(我还包含浏览器 UI 代码)并在将来超时时运行该函数。您在 100 毫秒时有 2 次超时,在 300 毫秒时有 1 次超时。请注意,代码可能不会以精确 100 毫秒运行。

标签: javascript arrays recursion settimeout


【解决方案1】:

setTimeout 不会阻止您的执行。因此,您几乎同时以相同的时间间隔排列三个函数:(100 毫秒内的点)、(300 毫秒内的破折号)、(100 毫秒内的点)

您会看到 100 毫秒后打印 dot 两次,300 毫秒后打印 dash 一次。

【讨论】:

    【解决方案2】:

    尽量把return morseCode(code.slice(0, -1));放在setTimeout里面,setTimeout是非阻塞的,如果你想达到你想要的,你需要在setTimeout里面调用morseCode

    【讨论】:

      【解决方案3】:

      这是另一种方法:

      let code = '...-..---..-..--.---'
        .split('')
        .map(char => char === '.' ? 'dot' : 'dash');
      
      function morse(arr){
        const word = arr.shift();
        const delay = word === 'dot' ? 100 : 500;
      
        console.log(word);
      
        if (arr.length) {
          setTimeout(morse, delay, arr);
        }  
      }
      
      morse(code);
      .as-console-wrapper { min-height: 100%!important; top: 0; }

      从超时回调函数内部开始“下一个”字母很重要,否则所有setTimeout 调用将从同一时间点开始计时。

      【讨论】:

      • 感谢@PeterSeliger 美化了我的回答。我通常写得很简洁,因为我喜欢在一页上阅读所有内容,但这可能更适合大多数读者。也感谢setTimeout 中第三个参数的提示。
      • 嘿,但又来了一个问题:为什么你认为使用===here 而不是== 很重要?难道较短的形式 (==) 也可靠地总是得到相同的结果吗?
      • 由于我非常喜欢这种方法,其目的不是纠正你,而是使代码对初学者更全面,因此也具有严格平等的特点,以适应 lint'ed 代码,即使它是没必要。
      【解决方案4】:

      函数的调用没有超时,试试这个:

      function morseCode(code) {
              let time = 0
              if (code.length === 0) {
                return;
              }
              let ele = code[code.length - 1];
              if (ele === "dot") {
                setTimeout(() => {
                  console.log("dot");
                }, 100);
                time = 100
              } else {
                setTimeout(() => {
                  console.log("dash");
                }, 300);
                time = 300
              }
              setTimeout(() => {
                return morseCode(code.slice(0, -1));
                }, time);
              
            }
            let code = ["dot", "dash", "dot"];
      
            morseCode(code);
      

      希望对你有帮助!

      【讨论】:

        【解决方案5】:

        另一种简单的递归写法:

        const morse = ([c, ...cs]) => 
          c !== undefined &&
          setTimeout (() => morse (cs), c == '.' ? 100 : c == '-' ? 500 : 1000) &&
          console .log (c == '.' ? 'dot' : c == '-' ? 'dash' : '')  
        
        morse ('.... . .-.. .-.. ---')
        .as-console-wrapper {max-height: 100% !important; top: 0}

        我们解构包含字符串的参数。如果第一个不存在,那么我们退出。如果是这样,我们设置一个超时以使用剩余的字符再次运行它,延迟由字符确定,然后我们记录与当前值匹配的“点”/“破折号”/空白字符。

        如果您不喜欢这种风格,则等价:

        const morse = ([c, ...cs]) => {
          if (c !== undefined) {
            const char = c == '.' ? 'dot' : c == '-' ? 'dash' : ''
            const delay = c == '.' ? 100 : c == '-' ? 400 : 800
            setTimeout (() => morse (cs), delay)
            console .log (char)  
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2019-10-18
          • 1970-01-01
          • 1970-01-01
          • 2012-10-09
          • 1970-01-01
          • 2017-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多