Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

手写一个防抖函数 #24

Open
Saikikoko opened this issue Mar 9, 2021 · 0 comments
Open

手写一个防抖函数 #24

Saikikoko opened this issue Mar 9, 2021 · 0 comments
Labels
Js knowledge of Javascript

Comments

@Saikikoko
Copy link
Owner

Saikikoko commented Mar 9, 2021

防抖多用于按钮点击,它的效果是在一段时间内无论多少次触发,只运行最后一次触发的动作。

下面首先对要实现的防抖函数的功能做一个前瞻

  1. 支持传入函数fn,返回一个新函数newFn
  2. 支持传入延迟时间delay
  3. 返回的新函数被多次触发,只运行最后一次
  4. 传入函数的this不会丢失
  5. 返回的新函数支持传入参数
  6. 支持立即执行
  7. 支持取消触发动作

防抖本质使用定时器和闭包实现的,如果在规定时间delay内重新触发动作,则清除定时器重新计时,下面写一个测试用例以及函数实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./09.js"></script>
</head>
<body>
  <div id="wrap">1</div>
</body>
<script>
  let count = 0
  wrap.addEventListener('mousemove', function() {
    console.log(this)
    this.innerText = ++count
  })
</script>
<style>
  body {
    background-color: #444;
  }
  #wrap {
    width: 1000px;
    height: 800px;
    font-size: 30px;
    text-align: center;
  }
</style>
</html>

不加防抖的效果就是数字增加的很快

function debounce(fn, delay, immedate) {
  let timer = null
  let result
  let cb = function(...args) {
    let context = this // 记录谁调用的新函数
    if (immedate && !timer) { // 立即执行
      result = fn.apply(context, args)
    }
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn.apply(context, args) // 可以向原来的函数传参
    }, delay)
    return result
  }
  cb.cancel = function() {
    clearTimeout(timer)
    timer = null
  }
  return cb
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./09.js"></script>
</head>
<body>
  <div id="wrap">0</div>
  <button onclick="fn.cancel()">取消</button>
</body>
<script>
  let count = 0
  let fn = debounce(function(e) {
    this.innerText = ++count
  }, 1000, true)
  console.log(fn.cancel)
  
  wrap.addEventListener('mousemove', fn)
</script>
<style>
  body {
    background-color: #444;
  }
  #wrap {
    width: 1000px;
    height: 800px;
    font-size: 30px;
    text-align: center;
  }
</style>
</html>

加了防抖以后,只在停止触发一秒以后执行

@Saikikoko Saikikoko added the Js knowledge of Javascript label Mar 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Js knowledge of Javascript
Projects
None yet
Development

No branches or pull requests

1 participant