この解答例はChatGPTによって生成されています,正しいかは自己判断で。 皆の投稿からも解答例が見つかるかもしれませんよ。

BFE.devでのAI解答例 - JavaScript コーディング問題
36. fake timer(setTimeout)を実装する

以下がJavaScriptのコードになります。

class FakeTimer {  constructor() {    this.timers = new Map()    this.currentTimestamp = 0  }    getCurrentTimestamp() {    return this.currentTimestamp  }  install() {    const originalSetTimeout = window.setTimeout    window.setTimeout = (func, delay, ...args) => {      const timer = setTimeout(func, delay, ...args)      this.timers.set(timer, {        func,        delay,        created: this.currentTimestamp      })      return timer    }        const originalClearTimeout = window.clearTimeout    window.clearTimeout = (timer) => {      this.timers.delete(timer)      originalClearTimeout(timer)    }    const originalDateNow = Date.now    Date.now = () => this.currentTimestamp  }  uninstall() {    window.setTimeout = setTimeout    window.clearTimeout = clearTimeout    Date.now = Date.now  }  tick(time) {    if (time === undefined) {      time = Math.max(1, ...Array.from(this.timers.values()).map((timer) =>         (timer.created + timer.delay) - this.currentTimestamp      ))    }    const remainingTimers = new Map()    this.timers.forEach((timer, timerId) => {      const elapsed = this.currentTimestamp - timer.created      const remainingTime = Math.max(0, timer.delay - elapsed)      if (remainingTime <= time) {        timer.func()      } else {        remainingTimers.set(timerId, {          ...timer,          delay: remainingTime        })      }    })    this.timers = remainingTimers    this.currentTimestamp += time  }}

この実装では、setTimeout()clearTimeout()、そしてDate.now() を上書きしています。setTimeout()は、実行予定の関数と経過時間を記録してタイマーIDを返します。clearTimeout()は、タイマーIDを引数にとって、対応する登録済みのタイマーを削除します。

tick() 関数は実装済みのタイマーを調べ、経過した時間に応じて適切なタイマーを実行します。一方、まだ経過時間が残っているタイマーは、再度登録してタイマー実行を予約します。time 引数が指定されている場合、 tick()が指定された時間まで進みます。

テストされているように、この実装によって setTimeout()clearTimeout() が経過時間を予測できることが期待されます。ただし、これらの関数が実行された時間を変更する必要性がある場合、これらの関数を呼び出す前に時間を変更する必要があります。