实现一个防抖-节流

# 实现一个防抖-节流

// 防抖
function debounce(fn, delay) {
 let timer = null
 let handle = function() {
  if (timer) {
   clearTimeout(timer)
  }
  timer = setTImeout(() => {
   fn()
  }, delay)
 }
 return handle
}

// 原函数带参数
function debounce(fn, delay) {
 let timer = null
 let handle = function() {
  if (timer) {
   clearTimeout(timer)
  }
  // 获取this和arguments
  let _this = this
  let _arguments = arguments
  timer = setTImeout(() => {
   fn.apply(_this, _arguments)
  }, delay)
 }
 return handle
}

// 带取消功能
function debounce(fn, delay) {
 let timer = null
 let handle = function() {
  if (timer) {
   clearTimeout(timer)
  }
  let _this = this
  let _arguments = arguments
  timer = setTImeout(() => {
   fn.apply(_this, _arguments)
  }, delay)
 }

 // 取消处理
 handle.cancel = function() {
  if (timer) {
   clearTimeout(timer)
  }
 }
 return handle
}

// 第一次立即执行
function debounce(fn, delay, leading) {
 let timer = null
 let handle = function() {
  if (timer) {
   clearTimeout(timer)
  }
  let _this = this
  let _arguments = arguments

  if (leading) {
   // 通过一个变量记录是否立即执行
   let isInvoke = false
   if(!timer) {
    fn.apply(_this, _arguments)
    isInvoke = true
   }
   timer = setTimeout(() => {
    timer = null
    if (!isInvoke) {
     fn.apply(_this, _arguments)
    }
   }, delay);
  } else {
   timer = setTImeout(() => {
    fn.apply(_this, _arguments)
   }, delay)
  }
 }
 return handle
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

不管事件触发频率多高, 一定在事件触发 n 秒后才执行

/**
 * @param {function} event
 * @param {number} time
 */
function debounce(event, time) {
  let timer = null

  return function (...args) {
    clearTimeout(timer)
    timer = setTimeout(() => {
      event.apply(this, args)
    }, time)
  }
}

// 立即执行一次,再等后面事件触发后等待 n 秒执行,用 flag 标示是否执行
/**
 * @param {function} event
 * @param {number} time
 * @param {boolean} flag
 */
function debounce(event, time, flag) {
  let timer = null

  return function (...args) {
    clearTimeout(timer)
    if (flag && !timer) event.apply(this, args)

    timer = setTimeout(() => {
      event.apply(this, args)
    }, time)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

不管事件触发频率多高,只在单位时间内执行一次

节流:固定时间内 就只执行一次

// # 时间戳实现: 第一次事件肯定触发,最后一次不会触发
/**
 * @param {function} event
 * @param {number} time
 */
function throttle(event, time) {
  let pre = 0
  return function (...args) {
    if (Date.now() - pre > time) {
      pre = Date.now()
      event.apply(this, args)
    }
  }
}

// # 定时器实现: 第一次事件不会触发,最后一次一定触发
/**
 * @param {function} event
 * @param {number} time
 */
function throttle(event, time) {
  let timer = null

  return function (...args) {
    if (!timer) {
      timer = setTimeout(() => {
        timer = null
        event.apply(this, args)
      }, time)
    }
  }
}

// # 结合版: 定时器和时间戳的结合版,也相当于节流和防抖的结合版,第一次和最后一次都会触发
/**
 * @param {function} event
 * @param {number} time
 */
function throttle(event, time) {
  let pre = 0
  let timer = null

  return function (...args) {
    if (Date.now() - pre > time) {
      clearTimeout(timer)
      timer = null
      pre = Date.now()
      event.apply(this, args)
    } else if (!timer) {
      timer = setTimeout(() => {
        event.apply(this, args)
      }, time)
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
上次更新: 2022/7/26 下午6:03:32