以下为ChatGPT自动生成的解答,正确与否请自行判断。 也许你也可以从大家的发帖中找到想要的答案!

BFE.devAI解答 - JavaScript 代码题
84. 创建一个fake timer (setInterval)

这道题目与 #36 非常相似,我们只需重新实现一个静态化的setInterval,实现的方法也非常类似,下面是具体实现:

class FakeTimer {  install() {    // 重写 setInterval 函数    this.oldSetInterval = window.setInterval;    window.setInterval = (func, delay) => {      const startTime = Date.now();      let intervalId;      const intervalFunc = () => {        const timePassed = Date.now() - startTime;        intervalId = this.oldSetInterval(intervalFunc, delay - timePassed);        func();      };      intervalId = this.oldSetInterval(intervalFunc, delay);      return intervalId;    };    // 重写 clearInterval 函数    this.oldClearInterval = window.clearInterval;    window.clearInterval = (intervalId) => {      this.oldClearInterval(intervalId);    };    // 重写 Date.now 函数    this.oldNow = Date.now;    let now = 0;    Date.now = () => now;  }  uninstall() {    window.setInterval = this.oldSetInterval;    window.clearInterval = this.oldClearInterval;    Date.now = this.oldNow;  }  tick() {    let intervalIds = [];    while (intervalIds.length) {      const id = intervalIds.shift();      this.oldClearInterval(id);    }    let now = 0;    dateNowFunc = Date.now;    Date.now = () => now;    setTimeoutFunc = window.setTimeout;    window.setTimeout = (func, delay) => {      const start = now;      intervalIds.push(        this.oldSetInterval(() => {          const timePassed = now - start;          if (timePassed >= delay) {            this.oldClearInterval(intervalIds.shift());            func();          }        }, 0)      );      return intervalIds[intervalIds.length - 1];    };    // 时间不断增加    function increaseTime(amount) {      now = now + amount;      tick();    }    function tick() {      for (let i = 0; i < intervalIds.length; i++) {        const id = intervalIds[i];        if (this.timeouts[id]) {          if (this.timeouts[id].timeoutTime <= now) {            const timeout = this.timeouts[id];            timeout.func.call(timeout.context);            // interval repitition            if (timeout.interval) {              timeout.timeoutTime = now + timeout.delay;            } else {              delete this.timeouts[id];            }          }        } else {          this.oldClearTimeout(id);        }      }    }    setInterval(() => {      now += 1000;      tick();    });    return increaseTime;  }}

来看具体的实现方法:

首先重写setInterval函数,使用一个 intervalFunc 作为间隔运行的函数,该函数会在delay时间后调用 func,同时,在每次运行时计算所用的时间,将延迟时间减已用时间就是下次函数运行的时间,从而实现间隔精度。

 window.setInterval = (func, delay) => {      const startTime = Date.now();      let intervalId;      const intervalFunc = () => {        const timePassed = Date.now() - startTime;        intervalId = this.oldSetInterval(intervalFunc, delay - timePassed);        func();      };      intervalId = this.oldSetInterval(intervalFunc, delay);      return intervalId; };

接下来重写clearInterval函数

window.clearInterval = (intervalId) => {      this.oldClearInterval(intervalId);};

最后是我们需要实现的时间轴函数,主要分为三个部分:

  1. tick(): 用于对于目前所有的定时器进行检查,是否已经超过设定的时间,从而决定是否执行 callback 函数;
  2. increaseTime(amount): 增加秒数的函数,用于测试时控制时间前进的速度
  3. setInterval(() => { ... }): 用于让时间时间不断增加
let now = 0;dateNowFunc = Date.now;Date.now = () => now;setTimeoutFunc = window.setTimeout;window.setTimeout = (func, delay) => {  const start = now;  intervalIds.push(    this.oldSetInterval(() => {      const timePassed = now - start;      if (timePassed >= delay) {        this.oldClearInterval(intervalIds.shift());        func();      }    }, 0)  );  return intervalIds[intervalIds.length - 1];};function increaseTime(amount) {  now = now + amount;  tick();}function tick() {  for (let i = 0; i < intervalIds.length; i++) {    const id = intervalIds[i];    if (this.timeouts[id]) {      if (this.timeouts[id].timeoutTime <= now) {        const timeout = this.timeouts[id];        timeout.func.call(timeout.context);        // interval repitition        if (timeout.interval) {          timeout.timeoutTime = now + timeout.delay;        } else {          delete this.timeouts[id];        }      }    } else {      this.oldClearTimeout(id);    }  }}setInterval(() => {  now += 1000;  tick();});return increaseTime;

最后就可以将三个函数组合起来,从而实现静态化的setIntervalclearInterval

完整代码如下: