最近在做网页的时候有个需求,就是浏览器窗口改变的时候需要改一些页面元素大小,于是乎很自然的想到了window的resize事件,于是乎我是这么写的

<!DOCTYPE html>
<html>
<head>
<title>Throttle</title>
</head>
<body>
<script type="text/javascript">
n=0;
function resizehandler(){
console.log(new Date().getTime());
console.log(++n);
} window.onresize=resizehandler;
</script>
</body>
</html>

功能倒是实现了,但是我拖拽的方式改变浏览器窗口大小的时候看了下控制台

没错,简单的一个拖拽让我的resizeHandler()方法执行了52次,这完全不是我想要的效果,实际上我的resizeHandler()方法的代码很复杂,甚至会使用ajax向服务器发送请求,要是简单的一次改变窗口大小就要调用52次这还了得

函数节流

其实我的本意只是窗口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">
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,delay){
var timer=null;
return function(){
var context=this, args=arguments;
clearTimeout(timer);
timer=setTimeout(function(){
method.apply(context,args);
},delay);
}
}

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

<script type="text/javascript">
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);

果真既没有频繁执行也没有就最后执行

Javascript函数节流的更多相关文章

  1. 浅谈javascript函数节流

    浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...

  2. 简述JavaScript函数节流

    为什么要用函数节流 浏览器中某些计算和处理要比其他的昂贵很多.例如,DOM 操作比起非 DOM 交互需要更多的内存和 CPU 时间.连续尝试进行过多的 DOM 相关操作可能会导致浏览器挂起,有时候甚至 ...

  3. javaScript函数节流与函数防抖

    javaScript函数节流与防抖之区别 函数防抖(debounce)与函数节流(throttle)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟.假死或卡顿 ...

  4. JavaScript函数节流与函数去抖

    介绍 首先解释一下这两个概念: 函数节流(throttle):是让一个函数无法在很短的时间间隔内连续调用,当上一次函数执行后过了规定的时间间隔,才能进行下一次该函数的调用. 函数去抖(debounce ...

  5. JavaScript函数节流(throttle)与函数去抖(debounce)

    对于浏览器窗口大小改变的时候,来动态改变页面元素的大小,可以采用window的resize事件,实现代码: <script type="text/javascript"> ...

  6. 再谈javascript函数节流

    之前写过但是不记得在哪了,今天同事要一个滑到页面底部加载更多内容的效果,又想起了这玩意儿,确实挺实用和常用的,谨此记之. 函数节流从字面上的意思就是节约函数的执行次数,其实现的主要思想是通过定时器阻断 ...

  7. 160722、Javascript函数节流

    最近在做网页的时候有个需求,就是浏览器窗口改变的时候需要改一些页面元素大小,于是乎很自然的想到了window的resize事件,于是乎我是这么写的 <!DOCTYPE html> < ...

  8. JavaScript 函数节流和函数去抖应用场景辨析

    概述 也是好久没更新 源码解读,看着房价蹭蹭暴涨,心里也是五味杂陈,对未来充满恐惧和迷茫 ...(敢问一句你们上岸了吗) 言归正传,今天要介绍的是 underscore 中两个重要的方法,函数节流和函 ...

  9. javascript 函数节流方法

    函数节流可以缓解调用的次数,代码如下: function throttle(method,delay){ var timer=null; return function(){ var context= ...

随机推荐

  1. sed笔记

    sed是stream editor缩写,表示流编辑器,它是一款文本处理工具,可以配合正则表达式进行文本替换. 1.使用正则表达式匹配并进行文本中的字符串替换 *使用-i选项可以直接将替换结果应用到源文 ...

  2. phpStudy 的Apache虚拟主机配置

    放弃了wamp,朋友介绍了phpstudy,不错的一款软件,关键是能自由切换php版本.相关的阿帕奇虚拟主机配置参考:http://www.th7.cn/system/win/201506/10846 ...

  3. JSNO

    JSON 编辑 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了 ...

  4. 1036. Crypto Columns 2016 11 02

    /* 对于题目多读几遍,然后再关键字排序的时候,把对应的数组序号也排序, EYDE    MBLR    THAN    MEKT    ETOE    EOTH        MEETME    B ...

  5. checkbox、全选反选,获取值

    <input id="Chk_All" onclick="CheckAll()" type="checkbox" /> < ...

  6. sql server 分布式查询 和 主从服务器搭建

    1. 8K 对应的SQL语句限制  select  *  from openquery (recei    连接服务器名称 执行的sql 语句放在   SELECT @@SERVERNAME  在本地 ...

  7. matlab 快捷键

    注释快捷键 ctrl + R 取消注释快捷键 ctrl + T 手动注释使用 % 连接两行(一行代码太长) 使用 ...

  8. Debian系统vim中文显示乱码问题

    网上查的一堆东西好像都不灵,试了半天! 先安装中文字体:sudo aptitude install fonts-arphic-uming fonts-wqy-zenhei 然后:sudo locale ...

  9. windows环境下修改Mysql的root密码

    最近一直没用Mysql,root密码给忘了,然后就自己修改了一下,现在整理一下步骤.(我的版本是5.1) 启动MySQL服务:>>net start mysql 关闭MySQL服务:> ...

  10. 页面超慢,zabbix却没报警

    故障背景:网站页面打开速度非常慢 排查过程: 1.一开始用vmstat 看到procs下的r值稳定在5.6,由于这台服务器是12核24线程,并且cpu的wa很大,说明系统很轻松, 肯定不会报警了,那为 ...