回答

分析

什么是防抖?

将n秒内连续触发的事件,以最后1次事件触发事件为准,来执行回调函数。
重点:触发后计时清除。
例如:电梯5秒后会关门开始运作,如果有人进来,等待5秒,5秒之内又有人进来,5秒等待重新计时。直至超过5秒,电梯才开始运作。

手写防抖

  1. // 使用setTimeout,clearTimeout实现
  2. let timeout: any;
  3. function debounce(fn: Function, wait: number) {
  4. clearTimeout(timeout);
  5. timeout = setTimeout(() => fn(), wait);
  6. }
  7. // test 3次输出间隔时间为3s
  8. function fn() {
  9. console.log(new Date().getSeconds(), "done");
  10. }
  11. fn();
  12. for (let i = 0; i < 100; i += 1) {
  13. debounce(fn, 3000);
  14. }
  15. setTimeout(() => {
  16. debounce(fn, 3000);
  17. }, 3001);
// 使用setTimeout,clearTimeout实现,并且将timeout放在函数内
function debounce(fn: Function, wait: number): Function {
  let timeout: any;
  return function () {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(), wait);
  };
}

// test 3次输出间隔时间为3s
function fn() {
  console.log(new Date().getSeconds(), "done");
}
let doFn = debounce(fn, 3000);

fn();
for (let i = 0; i < 100; i += 1) {
  doFn();
}
setTimeout(() => {
  doFn();
}, 3001);

什么是节流?

将n秒内连续触发的事件,以第1次事件触发时间为准,执行回调函数。
重点:触发后计时器不清除。
例如:电梯等第一个人进来之后,5秒后准时运作,不等待,若5秒内还有人进来,也不重置。

手写节流

// 使用setTimeout,一个标记变量实现
let able: boolean = true;
function throttle(fn: Function, wait: number) {
  if (able) {
    able = false;
    setTimeout(() => {
      fn();
      able = true;
    }, wait);
  }
}

// test 输出2次,每次间隔3s
function fn() {
  console.log(new Date().getSeconds(), "done");
}

for (let i = 0; i < 100; i += 1) {
  throttle(fn, 3000);
  setTimeout(() => {
    throttle(fn, 3000);
  }, 2000);
}
setTimeout(() => {
  throttle(fn, 3000);
}, 3001);
// 使用setTimeout,一个标记变量实现,并将标记变量放在函数内
function throttle(fn: Function, wait: number): Function {
  let able: boolean = true;
  return function () {
    if (able) {
      able = false;
      setTimeout(() => {
        fn();
        able = true;
      }, wait);
    }
  };
}

// test 输出2次,每次间隔3s
function fn() {
  console.log(new Date().getSeconds(), "done");
}
let doFn = throttle(fn, 3000);

for (let i = 0; i < 100; i += 1) {
  doFn();
  setTimeout(() => {
    doFn();
  }, 2000);
}
setTimeout(() => {
  doFn();
}, 3001);