浏览器的一些事件,如:resize,scroll,keydown,keyup,keypress,mousemove等。这些事件触发频率太过频繁,绑定在这些事件上的回调函数会不停的被调用。会加剧浏览器的负担,致使用户体验很是糟糕,不知哪一个大神发明了防抖和节流,用来控制回调函数的次数。javascript
//函数防抖(debounce) function debounce(fn, wait) { var timeout; return function() { if (timeout) { clearTimeout(timeout); } timeout = setTimeout(fn, wait); } } function handle() { console.log(12) } //滚动事件 window.addEventListener("scroll", debounce(handle, 1000))
代码解释:先执行debounce(handle, 1000)返回一个匿名函数,而后监听scroll事件,执行匿名函数,设置一个1秒后执行handle函数的定时器,因为scroll是不断触发的,若是第一次触发与第二次触发间隔1秒或者1秒多,第一次触发scroll会执行handle函数,在控制台上会打印12,若是间隔小于1秒,由于setTimeout(fn, wait)是要在1秒后执行handle 函数,小于1秒就不执行handle函数,可是timeout定时器已经不为空,第二次scroll滚动触发debounce时就执行clearTimeout(timeout),而且执行下面的代码,由于下面的代码不是放在else里面,依次类推。
总结:若是不停的触发事件,事件间隔大于设定的时间,才执行某个函数。html
若是是input的状况,这时须要传递数据前端
//函数节流(throttle) var throttle = function(func, delay) { console.log("hi") var prev = Date.now(); //返回1970 年 1 月 1日午夜与当前日期和时间之间的毫秒数。 return function() { var now = Date.now(); if (now - prev >= delay) { func() prev = Date.now() } } } function handle() { console.log(Math.random()) } window.addEventListener("scroll", throttle(handle, 1000))
解释:当持续触发事件时,每隔必定时间(如200ms)执行一次事件处理函数
先执行throttle(handle, 1000)返回一个匿名函数,而后触发scroll事件时执行返回的匿名函数,即未滚动的时候已经执行了throttle(handle, 1000)函数java
若是是input的状况(防抖)jquery
<body> <div style="" class=""> <input type="" id="unDebounce" /> </div> <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://apps.bdimg.com/libs/bootstrap/3.3.0/js/bootstrap.min.js"></script> <script type="text/javascript"> function ajax(content) { console.log("ajax request" + content) } function debounce(fun, delay) { var timeout; return function(args) { if (timeout) { clearTimeout(timeout) } timeout = setTimeout(function() { fun(args) }, delay) } } let inputElement = document.getElementById("unDebounce") let debounceAjax = debounce(ajax, 500) inputElement.addEventListener("keyup", function() { //debounceAjax(this.value)放在匿名函数里面的缘由是当keyup的时候才执行,若是不放在里面会先执行此函数,致使没有值 debounceAjax(this.value) }) </script> </body>
上面是用的闭包避免污染全局变量,用全局变量的写法更简单些ajax
<script type="text/javascript"> function handle(content){ console.log("input " + content); } var timeout; function debounce(value,handle,wait){ if(timeout){ clearTimeout(timeout) } timeout = setTimeout(function(){ handle(value) },wait) } var inputElement = document.getElementById("unDebounce"); inputElement.addEventListener("input",function(){ debounce(this.value,handle,500) }) </script>
若是是input的状况(节流) bootstrap
<body> <div style="" class=""> <input type="" id="throttle" /> </div> <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script> <script src="http://apps.bdimg.com/libs/bootstrap/3.3.0/js/bootstrap.min.js"></script> <script type="text/javascript"> function ajax(content) { console.log("ajax request" + content) } function throttle(func, delay) { var pre = Date.now(); var deferTimer; console.log("pre " + pre) return function(args) { var now = Date.now() console.log("now " + now) console.log(now - pre) if (now - pre >= delay) { func(args) pre = Date.now() } else { clearTimeout(deferTimer); deferTimer = setTimeout(function() { func(args) pre = Date.now() }, delay) } } } var throttleAjax = throttle(ajax, 2000) var inputc = document.getElementById('throttle') inputc.addEventListener('keyup', function() { throttleAjax(this.value) }) </script> </body>
防抖和节流的区别: 防抖是根据事件间隔是否大于设定的值来决定回调函数是否执行(取决于事件间隔,或者最后一次滚动); 节流是根据事件不停触发时时间间隔大于设定的值才执行回调函数(每隔多少秒执行一次);浏览器
公众号:前端之攻略闭包