Step-By-Step
Step-By-Step copied to clipboard
防抖(debounce)函数的作用是什么?有哪些应用场景,请实现一个防抖函数。
做一个类比,假设你和你的朋友chatty通过微信聊天,她非常的健谈,那么你有如下几种方式来处理她的消息:
- 最基本的就是时不时就看微信,这样会很浪费时间,但获取信息的实时性很高
- 函数节流: 每隔5分钟查看一次,这样获取信息的实时性不高,但是不会耽误你获取信息
- 函数防抖:假设她把她的故事分成了好几段发给你,你假定在5分钟内她没有再发信息就是整个故事已经发完了,然后再去查看。(函数防抖的非立即执行版)
在浏览器中,有很多事件比如window的onresize 鼠标的mousemove 以及滚轮事件wheel等,他们触发的很频繁,这个时候函数没必要一直执行。函数防抖就是让事件触发的n秒内只执行一次,如果连续触发就重新计算时间.
function debounce(fn, delay, immediate) {
let timer = null;
return function() {
clearTimeout(timer); //重新计算时间
let context = this;
let args = arguments;
if (!timer && immediate) {
fn.apply(context, args);
}
timer = setTimeout(function() {
if (!immediate) {
fn.apply(context, args);
} else {
timer = null;
}
}, delay)
}
}
防抖(debounce)在n秒内函数只被执行一次,如果在这个时间内再次被触发,则需要再次计算时间。 应用场景: 1、文本输入框的验证,输入完成之后验证一次即可,不需要每次都发请求验证。 2、size/scroll的触发统计事件。 实现:
function debounce(fn, delay, immediate) {
let timer = null;
return function() {
const context = this;
const args = arguments;
let result = undefined;
timer && clearTimeout(timer);
if (immediate) {
const doNow = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
if (doNow) {
result = fn.apply(context, args);
}
}
else {
timer = setTimeout(() => {
fn.apply(context, args);
}, delay);
}
return result;
};
}
在频繁触发某些事件,导致大量的计算或者非常消耗资源的操作的时候,防抖可以强制在一段连续的时间内只执行一次。
function debounce(fn, delay) {
let timer = null
return function() {
clearTimeout(timer)
let context = this
let args = arguments
timer = setTimeout(() => {
fn.apply(context, args)
}, delay)
}
}
在一定的时间间隔内只执行一次,如果重新触发则重新计算时间间隔。常见的场景如,远程搜索输入框、浏览器resize、scroll等,主要为了节约服务器性能。
function debounce(fn,delay){ let timer = null; return function(){ clearTimeout(timer); let args = arguments; let context = this; timer = setTimeout(()=>{ fn.apply(context,args)},delay) } }
防抖函数为了防止函数多次调用
const debounce = function (func,wait = 50) { // 缓存一个定时器id let timer = null; // 这里返回的函数时每次用户实际调用的防抖函数 // 如果已经设定过定时器了就清空上一次的定时器 // 开始一个定时器,延迟执行用户传入的方法 return function(...args){ if(timer) clearTimeout(timer); timer = setTimeout(()=>{ //将实际的this和参数传入用户实际调用的函数 func.apply(this,args); },wait); } }; 今天的题还是不会,参考了其他博客,感谢小姐姐 ,会努力学习跟大家一起进步~
防抖函数常用来进行处理某些频繁触发的请求事件,如input搜索事件,如果用户每输入一个字都发送一次请求那么则会非常耗费性能,所以用防抖函数进行限制,在一定时间内触发的事件只有到了指定的时间才发送一次请求。 var debounce = function(fn, delay = 100) { let timer = null; return function(...arg) { if (timer) { clearTimeout(timer) } timer = setTimeout(() => { fn.apply(this, arg) }, delay) } }
函数防抖 常用就是高频率触发一个函数时候,比如滚动条事件,窗口收缩,模糊搜索,每次滚动或者输入时候,都会触发函数执行,这样体验和性能都不好,防抖主要对性能优化,减少服务器负担
function throttle(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
防抖用于频繁操作的情况,比如输入关键字匹配下拉列表,由于输入是连续的因此为了提高性能,在一定时间内输入则采用防抖延迟请求时间 var timer = null function debounce(){ clearTimeout(timer) timer = setTimeout(function(){ console.log(1) }, 1000) }
防抖体会最深的,应该是下拉框的远程模糊搜索,不做防抖的话,每次用户输入变化,都立即请求服务器,对服务器负担太大。 function parent () { let timer =null ; return son () { clearTimeout(timer); timer = setTimeout(() => { // 请求 }, 300) // 这边设300ms的延迟 }
防抖函数的作用是限制用户的频繁操作,影响网页的性能,防抖函数的原理是如果用户频繁操作事件处理函数就不会执行,只有当进行了最后一次操作,并且时间大于设定的时间才会执行;防抖函数的应用十分广泛:比如:1.只有在用户最后一次改变页面尺寸时才做一些操作,2:当用户在搜索框停止输入后发起Ajax请求;
function debounce(fn, wait, immediate = false) {
let timer = null
return function(...arg){
if(immediate) {
fn.apply(this,arg)
immetiate = false
}
timer ? clearTimout(timer) : ""
timer = setTimeout(()=>{
fn.apply(this.arg)
},wait)
}
}
防抖函数概念作用:
函数防抖(debounce)是指在一定时间内,在动作被连续频繁触发的情况下,动作只会被执行一次,也就是说当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间,所以短时间内的连续动作永远只会触发一次,比如说用手指一直按住一个弹簧,它将不会弹起直到你松手为止。
目的:为了限制函数执行频率,优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟或者卡死的现象
防抖就是防止频繁的调用函数
应用场景:
window对象的resize,scroll事件。 拖拽的mousemove,mousedown事件。 文字输入,keyup、keydown事件。 加载更多. 实现一个防抖函数 function debounce(func, wait, immediate) { var timeout, result; var debounced = function () { var context = this; var args = arguments; if (timeout) clearTimeout(timeout); if (immediate) { // 如果已经执行过,不再执行 var callNow = !timeout; timeout = setTimeout(function(){ timeout = null; }, wait) if (callNow) result = func.apply(context, args) } else { timeout = setTimeout(function(){ func.apply(context, args) }, wait); } return result; }; debounced.cancel = function() { clearTimeout(timeout); timeout = null; }; return debounced; } d ----嘤嘤嘤,不怎么会实现,只知道概念,期待小姐姐的怎么实现的
1.防抖函数作用和应用场景: 函数防抖是指对于在事件被触发n秒后再执行的回调,如果在这n秒内又重新被触发,则重新开始计时,是常见的优化,适用于 (1)表单组件输入内容验证 (2)防止多次点击导致表单多次提交等情况,防止函数过于频繁的不必要的调用。 2.防抖函数: function debounce(func, wait, immediate) { let time let debounced = function() { let context = this if(time) clearTimeout(time)
if(immediate) {
let callNow = !time
if(callNow) func.apply(context, arguments)
time = setTimeout(
()=>{time = null} //见注解
, wait)
} else {
time = setTimeout(
()=>{func.apply(context, arguments)}
, wait)
}
}
return debounced
} (微信名:RUN)
防抖函数(debounce): 含义:触发事件后在n秒之内只触发函数一次,如果在n秒事件内再次触发事件,则n归零,重新计算时间。 应用场景:input输入框输入信息请求后台数据,若输入一个字便请求一次服务器,会增加服务器压力,耗费性能。频繁点赞取消点赞、window触发resize、手机或邮箱的验证等。 目的:限制函数触发频率; 实现核心:维护一个setTimeout,在冷却时间内再次触发函数则清空原setTimeout重新计算一个setTimeout推入队列等待执行。
function debounce(func,wait){
var timeout;
return function(){
var context = this;
var args = arguments;
clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(context,args);
},wait)
}
}
在日常工作中,有三种场景我使用了防抖 比如搜索框change时查询接口、scroll、resize事件被触发
什么是防抖
所谓防抖,就是指触发事件后在n秒内只能执行一次,如果在n秒内触发事件的,则会重新计算函数执行事件
防抖的两种状态
立即执行和非立即执行 非立即执行 触发事件后函数不会立即执行,而是在n后开始执行
<body>
<div id="content"
style="height:1000px;line-height: 1000px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;">
1
</div>
<script>
// 非立即执行版
function debounce(func, wait) {
let timeout
return function () {
let context = this;
let args = arguments;
console.log(context, args);
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args);
}, wait)
}
}
let num = 1;
let content = document.getElementById('content');
function count() {
content.innerHTML = num++;
}
window.addEventListener("scroll", debounce(count,1000));
</script>
</body>
立即执行 触发事件后函数立即执行
function debounce(func,wait){
let timeput;
return function(){
let context = this;
let args = arguments;
if(timeout){
clearTimeout(timeout)
}
let callNow = !timeout;
timeout = setTimout(() =>{
timeout = null
},wait)
if(callNow) func,apply(context,args)
}
}
防抖意思懂,函数吧,就写不来了,看了别人写的,稍微懂了点 function throttle(func, wait) { let timeout; return function() { let context = this; let args = arguments; if (!timeout) { timeout = setTimeout(() => { timeout = null; func.apply(context, args) }, wait) } } }
函数防抖 常用就是高频率触发一个函数时候,比如滚动条事件,窗口收缩,模糊搜索,每次滚动或者输入时候,都会触发函数执行,这样体验和性能都不好,防抖主要对性能优化,减少服务器负担 function debounce(func,wait){ var timeout; return function(){ var context = this; var args = arguments;
clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(context,args);
},wait)
}
}
防抖简单来说就是一段时间内只触发一次,跟节流很像(隔一段时间执行一次) 防抖多数是用来高频率触发,但是每一次触发又不是必须要处理的情况,比如input的onchanage、document的onscroll,window的onresize。 function debounce(fn, time){ var timer = null; return function(){ timer ? clearTimeout(timer) : null; timer = setTimeout(()=> fn(),time); } }
关于 debounce 和 throttling 的区别,推荐一篇文章吧
https://css-tricks.com/debouncing-throttling-explained-examples/
关于 debounce 和 throttling 的区别,推荐一篇文章吧
https://css-tricks.com/debouncing-throttling-explained-examples/
谢谢给大家推荐好文,但是也别忘了好好阅读一下哈~
防抖函数为了防止函数多次调用
const debounce = function (func,wait = 50) { // 缓存一个定时器id let timer = null; // 这里返回的函数时每次用户实际调用的防抖函数 // 如果已经设定过定时器了就清空上一次的定时器 // 开始一个定时器,延迟执行用户传入的方法 return function(...args){ if(timer) clearTimeout(timer); timer = setTimeout(()=>{ //将实际的this和参数传入用户实际调用的函数 func.apply(this,args); },wait); } }; 今天的题还是不会,参考了其他博客,感谢小姐姐 ,会努力学习跟大家一起进步~
今日又比昨天进步了,这一点就已经超级赞了~ 一起努力~每天进步一点点~
函数防抖:任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。
应用场景: 楼上 @wangzhijun-github 同学总结的挺好的。防抖多数是用来高频率触发,但是每一次触发又不是必须要处理的情况,比如input的onchanage、document的onscroll,window的onresize,还有onmousemove。当然有些情况节流函数也可以达到节省资源的效果。
- 输入框键入 以用户注册时,验证用户名是否被占用为例,如今很多网站为了提高用户体验,不会在输入框失去焦点的时候再去判断用户名是否被占用,而是在输入的时候就在判断这个用户名是否已被注册,但每次输入都会像服务端发送请求,毫无疑问是没有意义的,实际上在用户停止键入时进行查询更为合理。
// 每次输入都发生请求
$('input.user-name').on('input', function () {
$.ajax({
url: `https://just.com/check`,
method: 'post',
data: {
username: $(this).val(),
},
success(data) {
if (data.isRegistered) {
$('.tips').text('该用户名已被注册!');
} else {
$('.tips').text('恭喜!该用户名还未被注册!');
}
},
error(error) {
console.log(error);
},
});
});
未优化效果图:
// 添加防抖函数
function debounce(fn, interval = 300) {
let timeout = null;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, interval);
};
}
$('input.user-name').on('input', debounce(function () {
$.ajax({
url: `https://just.com/check`,
method: 'post',
data: {
username: $(this).val(),
},
success(data) {
if (data.isRegistered) {
$('.tips').text('该用户名已被注册!');
} else {
$('.tips').text('恭喜!该用户名还未被注册!');
}
},
error(error) {
console.log(error);
},
});
}));
防抖函数效果图:
今日答题完成,感谢小姐姐带我们成长
- mouseover 、scroll 、resize、keyup 事件会频繁触发,会导致页面卡顿,所以希望多次触发的相同事件触发合并成一次触发
- 作用: 在某段连续时间内,在事件触发后只执行一次
/**
* @param fn {Function} 实际要执行的函数
* @param interval {Number} 延迟时间,默认 300 毫秒
*
* @return {Function}
*/
function debounce(fn, interval = 300) {
let timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(() => {
fn.applay(this, arguments);
}, interval);
}
}
防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
function debounce(fn, wait) {
var timer = null;
return function () {
var that = this
var args = arguments
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function () {
fn.apply(that, args)
}, wait)
}
}
var fn = function () {
console.log('boom')
}
setInterval(debounce(fn,500),1000) // 第一次在1500ms后触发,之后每1000ms触发一次
setInterval(debounce(fn,2000),1000) // 不会触发一次(我把函数防抖看出技能读条,如果读条没完成就用技能,便会失败而且重新读条)
节流:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。
function throttle(fn, gapTime) {
let _lastTime = null;
return function () {
let _nowTime = + new Date()
if (_nowTime - _lastTime > gapTime || !_lastTime) {
fn();
_lastTime = _nowTime
}
}
}
let fn = ()=>{
console.log('boom')
}
setInterval(throttle(fn,1000),10)
防抖函数作用
出现的原因
在某段连续时间内,多次触发请求 为造成资源浪费,为了解决客户端的性能问题 出现了防抖
什么是防抖
在某段连续时间内在事件触发后只执行一次
作用
解决高频繁问题,既能节省浏览器CPU资源,又能让页面浏览更加顺畅,不会因为js的执行而发生卡顿 出现场景:最常见的是搜索引擎 input 输入
实现
fangdou(fn, delay) { let timeout; let _arg; return function(arg) { _arg = arg; if (timeout) { clearTimeout(timeout); } timeout = setTimeout(() => { fn.call(this, _arg); }, delay); }; }
防抖函数的作用是防止频繁触发某个事件
原理:利用定时器,当事件触发后一段该事件内再次触发,则重新开始计时,等到计时器结束之后,才做该事件的响应
应用场景:最常见的就是搜索框了,当我们一直键入的时候,键盘事件一直在触发,但是只有我们不键入一会,搜索框才会带着关键词去请求响应的数据回来。防抖减少网络请求等事件的次数。
写一个防抖:
function debounce(fn,interval) {
let timer
return function(...args) {
if (timer) return false
timer = setTimeout(() => {
fn(...args)
clearTimeout(timer)
}, interval)
}
}
const fn = debounce((...args) => console.log(args),1000)
fn(1,2)
fn(2,3)
fn(4,5)
fn(4,2)
// 只输出[1,2]
fn函数频繁调用,却只输出一次!
本题我重点从防抖的作用、概念应用场景、手写防抖函数方面回答,同时通过防抖和节流的区别,加深自己对防抖和节流知识点的理解。
一、概念
(一)防抖(debounce)的概念
防抖是触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法。
(二)节流(throttle)的概念
节流是高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。每次触发事件时,如果当前有等待执行的延时函数,则直接return。
二、作用
(一)防抖的作用
如果我们对函数的调用频率无限制,比如在实现模糊查询的时候,既会加重浏览器的负担,也会加重服务器的负担,防抖可以减少函数的调用频率,不影响功能的情况下,提升用户体验。
(二)节流的作用
节流就是在一定时间间隔内触发一次事件。减少触发事件的频率,提升性能。
三、防抖(debounce)和节流(throttle)的区别
函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,列入水管的水滴在一定的间隔时间滴一滴水。而函数防抖只是在最后一次事件后才触发一次函数,如果中途再次触发,则再次重新开始计算时间,重新延迟。
四、应用场景
(一)防抖的应用场景
1、模糊查询
(二)节流的应用场景
1、滚动页面
五、手写代码
(一)手写防抖
通过定义一个是否执行函数的canRun标识,在没有超过约定时间内,如果再次触发函数,清除定时器,重新计算时间,直到到了约定时间后,才会调用函数。比如在实现模糊查询的时候,每个500ms向后台发起一个请求
- 实现思路 每次调用函数时,先清除定时器,重新计算时间,直到满足约定的时间后,再清除定时器
function debounce(fn, wait) {
var timeout = null;
return function() {
if(timeout !== null) {
clearTimeout(timeout);
}
timeout = setTimeout(fn, wait);
}
}
// 处理函数
function handle() {
console.log(Math.random());
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));
##(二)手写节流
- 实现思路 调用函数时,通过上一次pre和现在now两个变量,记录调用时间的频率,prev-now 如果大于约定的时间,才调用函数。调用函数结束后,把pre设置为现在的时间。
var throttle = function(func, delay) {
var prev = Date.now();
return function() {
var context = this;
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
}
}
function handle() {
console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));
六、参考文章
结语 我的回答如有不对的地方,麻烦务必指出来,我及时改正,以免误导别人,让我们共同进步吧!
今天这个题看一些博客,还是有点不解,可能是在平时没有用到过的原因,这个防抖说的大概意思就是,函数执行完一次再去触发执行第二次,如果是这样的话,设置一个开关是否可行,还有设置一个倒计时,函数触发后倒计多少秒后在执行; 看了以上的各位的写的都差不多,还是对其一些传参不解,今天先记录一下吧;
var timer = null function debounce(){ clearTimeout(timer) timer = setTimeout(function(){ console.log(1) }, 1000) } https://css-tricks.com/debouncing-throttling-explained-examples/值得一看 https://mp.weixin.qq.com/s/Vkshf-nEDwo2ODUJhxgzVA
防抖
防抖(debounce
) :当持续触发事件时,一定时间内没有再触发事件,事件处理函数才会执行* 一次 *,如果设定时间到来之前,又一次触发了事件,就重新开始延时。
function debounce(fn,delay){
let timer = null;
return function(){
let ctx = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(()=>{
fn.apply(ctx,args);
},delay);
}
}
防抖函数的应用
- input输入框,在用户不断输入值时,用防抖来节约请求资源(百度输入框)
- 邮箱,手机号等验证输入检测
- window 触发resize的时候,不断调整窗口大小会不停的触发这个事件,可以用防抖来让其处理函数只触发一次
说了防抖,还有一个跟防抖比较类似的概念 :节流(throttle
)
节流
节流(throttle
):当持续触发事件时,* 一定时间内只调用一次* 事件处理函数
function throttle(fn,delay){
let timer = null;
return function(){
let ctx = this;
let args = arguments;
if(timer === null){
timer = setTimeout(()=>{
fn.apply(ctx,args);
timer = null;
},delay)
}
}
}
节流函数的应用
- 滚动条滚动底部加载更多,监听滚动条位置
- canvas动画函数
requestAnimationFrame
区别
虽然防抖和节流很像,他们都是在持续触发事件时,做一些相应的操作来实现节省资源,但是还是有一些不同
- 防抖是规定时间内连续触发事件时,不会执行事件处理函数,当连续事件不触发时,之后的规定时间后触发一次
- 节流是连续触发事件时,每隔一定的时间就会触发一次事件处理函数
在前端开发的过程中,我们经常会需要绑定一些持续触发的事件,如 resize、scroll、mousemove 等等,但有些时候我们并不希望在事件持续触发的过程中那么频繁地去执行函数。
防抖函数分为非立即执行版和立即执行版。
非立即执行版 触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。(url)
function(url) debounce(func, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args)
}, wait);
}
}
立即执行版 触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
function debounce(func,wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
}
防抖,又称函数节流,背后基本思想是指:某些代码不可以没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数请求停止了一段时间之后才执行。
function throttle(fn, context){
clearTimeout(fn.tId);
fn.tId = setTimeout(function(){
fn.apply(context, arguments)
},200)
}
节流在resize事件中是最常用的,如下案例,设置一个div的高度适中和宽度保持一致 案例:
function resizeDiv(){
var div = document.getElementById('#myDiv');
div.style.height = div.offsetWidth + 'px';
}
window.onresize = function(){
throttle(resizeDiv);
}