对于浏览器窗口大小改变的时候,来动态改变页面元素的大小,可以采用window的resize事件,实现代码:

<script type="text/javascript">
var n = 0;
function resizehandler(){
console.log(new Date().getTime());
console.log(++n);
} window.onresize = resizehandler;
</script>

功能能够实现,都是当我们用拖拽的方式改变浏览器大小的时候,控制台会不断打印执行resizehandler的函数的结果。

一次简单的拖拽会让resizehandler()函数执行很多次,实际在显示项目中resizehandler函数可能会很复杂,甚至会涉及到前后端的数据交互,所以一次拖拽执行很多次很明显是不能够接受的。

函数去抖

其实我们的本意只是窗口resize后页面做一些调整就可以了,而window的resize事件并不是在resize结束后才出发,具体的触发频率不是很清楚,但却在不停地调用,直到窗口大小不在变化。类似的机制还有鼠标的mousemove,都是在短时间内重复触发。

在《JavaScript高级程序设计》中有专门应对此问题的函数防抖

function throttle(method, context){
clearTimeout(method.tId);
method.tId = setTimeout(function(){
method.call(context);
}, 500);
}

原理很简单,利用定时器,让函数执行延迟500毫秒,在500毫秒内如果有函数又被调用则删除上一次的调用,这次调用500毫秒后执行,如此往复。这样刚才的代码可以改为:

<script type="text/javascript">
var n = 0;
function resizehandler(){
console.log(new Date().getTime());
console.log(++n);
} function throttle(method, context){
clearTimeout(method.tId);
method.tId = setTimeout(function(){
method.call(context);
}, 500);
} window.onresize = function(){
throttle(resizehandler, window);
};
</script>

这样的话执行就没有问题了。

函数防抖的另一种方法

预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个周期。

function throttle(method, dalay){
var timer = null;
return function(){
var context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
method.apply(context, args);
}, delay);
}
}

调用一下试试,一样的效果

<script type="text/javascript">
var n = 0;
function resizehandler(){
console.log(new Date().getTime());
console.log(++n);
} function throttle(method, delay){
var timer = null;
return function(){
var context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
method.apply(context, args);
}, delay);
}
} window.onresize = throttle(resizehandler, 500); //这里因为返回函数句柄,不用包装函数了。
</script>

比较

两种方法都是利用了setTimeout,不同的是第二种方法加入的函数延迟执行时间,这个在第一种方案中很容易也具有的功能,无非是加一个参数。

但是第一种方案把tId设为函数的一个变量保存,而第二种创建了闭包存储。个人觉得差距不大,很喜欢第一种,简单,高效。

新需求

百度首页输入自动提示一样的东西,我在text上绑定keyup事件,每次键盘弹起的时候自动提示,但是又不想提示那么频繁,于是我用了上面方法,但是悲剧了,只有挺直输入等500毫秒才会提示,在输入过程中根本就没有提示。看了一下代码,可不是嘛,只有用户会盲打,在500毫秒内按一下键盘,提示函数就会不断被延迟,这样只有停下来的时候才会提示,这就没有意义了。

能不能在函数节流的基础上间隔固定时间就执行一次?

函数节流

在网上搜了一下我们可以根据第二种下发(第一种函数拓展多个变量感觉有些不好)做些改动,添加一个参数作为到固定间隔必须执行。

function throttle(method, delay, duration){
var timer = null, begin = new Date();
return function(){
var context = this, args = arguments, current = new Date();
clearTimeout(timer);
if(current-begin >= duration){
method.apply(context, args);
begin = current;
} else {
timer = setTimeout(function(){
method.apply(context, args);
}, delay);
}
}
}

这样每次我们判断间隔了够久,要是超过设置时间则立即执行一次,以刚才的例子试一试效果

window.onresize = throttle(resizehandler, 100, 200);

这样,既没有频繁执行也没有就最后执行。

总结

对于函数节流在做动态响应用户行为方面有较大的使用频率,具体使用基础版本的函数节流还是改动版本的还要根据业务场景进行具体分析。

throttle和debounce均是通过减少实际逻辑处理过程的执行来提高事件处理函数运行性能的手段,并没有实质上减少事件的触发次数。 (逃)

JavaScript函数节流(throttle)与函数去抖(debounce)的更多相关文章

  1. [JavaScript] 函数节流(throttle)和函数防抖(debounce)

    js 的函数节流(throttle)和函数防抖(debounce)概述 函数防抖(debounce) 一个事件频繁触发,但是我们不想让他触发的这么频繁,于是我们就设置一个定时器让这个事件在 xxx 秒 ...

  2. javascript 函数节流 throttle 解决函数被频繁调用、浏览器卡顿的问题

    * 使用setTimeout index.html <html> <head> <meta charset="UTF-8"> <title ...

  3. js 函数节流throttle 函数去抖debounce

    1.函数节流throttle 通俗解释: 假设你正在乘电梯上楼,当电梯门关闭之前发现有人也要乘电梯,礼貌起见,你会按下开门开关,然后等他进电梯: 但是,你是个没耐心的人,你最多只会等待电梯停留一分钟: ...

  4. JS中的函数节流throttle详解和优化

    JS中的函数节流throttle详解和优化在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(mousemove),这种事件有一个特点,在一个正常的操作中,有可能在一个短的 ...

  5. 函数节流throttle和防抖debounce

    throttle 函数节流 不论触发函数多少次,函数只在设定条件到达时调用第一次函数设定,函数节流 1234567891011 let throttle = function(fn,intervalT ...

  6. js 高程 函数节流 throttle() 分析与优化

    在 js 高程 22.3.3章节 里看到了 函数节流 的概念,觉得给出的代码可以优化,并且概念理解可以清晰些,所以总结如下: 先看 函数节流 的定义,书上原话(斜体表示): 产生原因/适用场景: 浏览 ...

  7. 微信小程序:防止多次点击跳转(函数节流)

    场景 在使用小程序的时候会出现这样一种情况:当网络条件差或卡顿的情况下,使用者会认为点击无效而进行多次点击,最后出现多次跳转页面的情况,就像下图(快速点击了两次): 解决办法 然后从 轻松理解JS函数 ...

  8. 【Javascript函数】节流throttle和间隔控制dbounce

    一.throttle 函数节流,指把很小时间内触发的N多事件,节流成1个事件. 我们这里说的throttle就是函数节流的意思.再说的通俗一点就是函数调用的频度控制器,是连续执行时间间隔控制.主要应用 ...

  9. 深入理解javascript函数进阶系列第三篇——函数节流和函数防抖

    前面的话 javascript中的函数大多数情况下都是由用户主动调用触发的,除非是函数本身的实现不合理,否则一般不会遇到跟性能相关的问题.但在一些少数情况下,函数的触发不是由用户直接控制的.在这些场景 ...

  10. JS的函数节流(throttle)

    什么是函数节流? 介绍前,先说下背景.在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(其核心就是绑定mousemove),这种事件有一个特点,就是用户不必特地捣乱,他在 ...

随机推荐

  1. netty客户端源码

    随笔记录. //创建一个ChannelFactory(客户端代码) ChannelFactory factory = new NioClientSocketChannelFactory( Execut ...

  2. hadoop2.7的目录结构

    1.$HADOOP_HOME/bin目录下文件及作用 文件名称 说明 hadoop 用于执行hadoop脚本命令,被hadoop-daemon.sh调用执行,也可以单独执行,一切命令的核心 2.$HA ...

  3. Json.Net 在.Net Core 2.0 中序列化DataSet 问题

    使用Asp.Net Core中自带的版本10.0.1 生成一个简单的DataSet DataSet ds2 = new DataSet(); DataTable table = new DataTab ...

  4. 帝国CMS-后台管理工具

    后台管理工具 apache+mysql 搭建的后台管理工具 参考手册*************http://www.phome.net/doc/ecmsedu/ 1.安装----- 使用的一键安装包. ...

  5. Solidity的自定义结构体深入详解

    一.结构体定义 结构体,Solidity中的自定义类型.我们可以使用Solidity的关键字struct来进行自定义.结构体内可以包含字符串,整型等基本数据类型,以及数组,映射,结构体等复杂类型.数组 ...

  6. 【IT笔试面试题整理】字符串的组合

    [试题描述]输入一个字符串,输出该字符串中字符的所有组合.举个例子,如果输入abc,它的组合有a.b.c.ab.ac.bc.abc. 分析:这是一道很好的考查对递归理解的编程题,因此在过去一年中频繁出 ...

  7. 自制 Chrome Custom.css 设置网页字体为微软雅黑扩展

    自己做的將網頁自動替換為微軟雅黑的擴展.很好用. 將Customcss.rcx拖到擴展裏就可. 下載:Customcss.zip

  8. Curling 2.0(DFS简单题)

    题目链接: https://vjudge.net/problem/POJ-3009 题目描述: On Planet MM-21, after their Olympic games this year ...

  9. MSSQL如何将查询结果拼接成字符串

    在博问上看到一个提问“MSSQL如何将查询结果拼接成字符串” ,想了一下应该怎么实现呢,在c#等语言下好实现,但在sql里实现.还真没做过. 目标:想要在SQL中将查询的结果拼接为 '1','2',' ...

  10. API 与 SDK

    API 和SDK是软件行业的两个缩写词. API (Application Programming Interface)=应用程序编程接口 通过一套套的要求,用来管理应用程序之间的沟通.一个API相当 ...