js 高程 函数节流 throttle() 分析与优化
在 js 高程 22.3.3章节 里看到了 函数节流 的概念,觉得给出的代码可以优化,并且概念理解可以清晰些,所以总结如下:
先看 函数节流 的定义,书上原话(斜体表示):
产生原因/适用场景:
浏览器中某些计算和处理要比其他的昂贵很多。例如,DOM 操作比起非 DOM 交互需要更多的内存和 CPU 时间。连续尝试进行过多的 DOM 相关操作可能会导致浏览器挂起,有时候甚至会崩溃。尤其在 IE 中使用onresize 事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件会连续触发。
在onresize 事件处理程序内部如果尝试进行 DOM 操作,其高频率的更改可能会让浏览器崩溃。为了绕开这个问题,你可以使用定时器对该函数进行节流。
基本思想:
函数节流背后的基本思想是指,某些代码不可以在没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。
我的理解:
譬如 onresize 和 onmouseover 事件,在 缩放浏览器 和 鼠标滑过 时,是不间断触发的,仅仅是 缩放下浏览器 和 滑过鼠标 这个看似简单的动作,其实已经触发了 n 次 onresize 和 onmouseover 事件了,如果绑定的事件处理程序又有点复杂,那这个 n 次执行时很耗资源的;
举例:
function mouseoverConsole() {
console.log('mousemove');
}
document.onmouseover = mouseoverConsole;
这个代码很简单,如果我们鼠标滑过下文档,你会发现:
仅仅是滑下,这个 mouseoverConsole 就执行了 13次,如果用户滑过的次数多些,时间久些,那么这个 mouseoverConsole 就会执行更多次,如果这个函数本身不耗资源也就算了,如果很耗资源呢,那就可能造成页面卡顿;
再举个例子,onresize 事件,可能会造成浏览器重新计算布局,如果布局很复杂,在缩放浏览器的时候,onresize 事件又在不断触发,就可能造成浏览器卡顿,虽然用户缩放浏览器可能只用了1s不到,但是触发了 onresize 事件可能有20次,然而 onrsize 触发的第一次事件处理程序可能还没执行完,而后面还有 19 次需要执行,自然就会卡顿;
那么如果说,第一次的还在执行或还没执行,在 100ms 内又触发了 9 次,那么实际上,直接执行第 10 次的事件处理程序就可以了,因为,100ms 内页面调整 10 次 和调整 1 次,用户是区分不出来的,但是运行 10 次 和 1 次对于浏览器而言所耗资源是不一样的,尤其是事件处理程序复杂时;这就是我理解的 函数节流 的思想;
函数节流优点:
节省资源,案例见上例子;
函数节流缺点:
效果延时,动态效果受影响,不过可以通过缩短间隔时间来优化解决,比如 100ms 改成 10ms;
譬如,极端点,如果用户一直在不停滑鼠标,中间 100ms 都没有停过,那么根据函数节流的思想,绑定的事件处理程序就一直不会执行,直到,用户停下来有 100ms 的时间才会开始执行绑定的事件处理程序;就像你缩放浏览器一直没停,那么页面就会在你停下来的时候才会调整,自然你就看不到中间缩放时页面的变化;
因为第 2 次触发会把第一次的事件处理程序停掉,第 3 次的停第 2 次的,一直到中间停下来 100ms ,那么当次的事件处理程序才会执行;当然如果把 100ms 改成 10ms ,缺点就会降低,当然所占资源就会增加,所以中间的间隔时间提供了一个选择,可以修改间隔时间来平衡性能和效果;
下面来上代码,书上代码,关于 apply() ,arguments 不明白的看 这里:
普通代码,不进行函数节流:
window.onresize = function() {
var div = document.getElementById("myDiv");
div.style.height = div.offsetWidth + "px";
};
函数节流代码:
window.onresize = function() {
throttle(resizeDiv);
}; function throttle(method, context) {
clearTimeout(method.tId);
method.tId = setTimeout(function() {
method.call(context);
}, 100);
} function resizeDiv() {
var div = document.getElementById("myDiv");
div.style.height = div.offsetWidth + "px";
}
这里,调整大小的功能被放入了一个叫做 resizeDiv() 的单独函数中。然后onresize 事件处理程序调用throttle()并传入 resizeDiv 函数,而不是直接调用 resizeDiv()。多数情况下,用户是感觉不到变化的,虽然给浏览器节省的计算可能会非常大。
只要代码是周期性执行的,都应该使用节流,但是你不能控制请求执行的速率。这里展示的 throttle() 函数用了 100ms 作为间隔,你当然可以根据你的需要来修改它。
我自己优化了下,这样调用的时候更简单,可以直接设置 时间间隔(平衡性能和展示),且可以传递 event 对象;
document.onmouseover = throttle(mouseoverConsole,100); function throttle(method,interval,context) {
return function() {
var args = arguments;
clearTimeout(method.timeoutId);
method.timeoutId = setTimeout(function() {
method.apply(context, args);
}, interval);
};
} function mouseoverConsole(event) {
console.log(event.type);
}
js 高程 函数节流 throttle() 分析与优化的更多相关文章
- [JavaScript] 函数节流(throttle)和函数防抖(debounce)
js 的函数节流(throttle)和函数防抖(debounce)概述 函数防抖(debounce) 一个事件频繁触发,但是我们不想让他触发的这么频繁,于是我们就设置一个定时器让这个事件在 xxx 秒 ...
- JS中的函数节流throttle详解和优化
JS中的函数节流throttle详解和优化在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(mousemove),这种事件有一个特点,在一个正常的操作中,有可能在一个短的 ...
- [概念] js的函数节流和throttle和debounce详解
js的函数节流和throttle和debounce详解:同样是实现了一个功能,可能有的效率高,有的效率低,这种现象在高耗能的执行过程中区分就比较明显.本章节一个比较常用的提高性能的方式,通常叫做&qu ...
- JS的函数节流(throttle)
什么是函数节流? 介绍前,先说下背景.在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(其核心就是绑定mousemove),这种事件有一个特点,就是用户不必特地捣乱,他在 ...
- js 函数节流throttle 函数去抖debounce
1.函数节流throttle 通俗解释: 假设你正在乘电梯上楼,当电梯门关闭之前发现有人也要乘电梯,礼貌起见,你会按下开门开关,然后等他进电梯: 但是,你是个没耐心的人,你最多只会等待电梯停留一分钟: ...
- 函数节流throttle和防抖debounce
throttle 函数节流 不论触发函数多少次,函数只在设定条件到达时调用第一次函数设定,函数节流 1234567891011 let throttle = function(fn,intervalT ...
- javascript 函数节流 throttle 解决函数被频繁调用、浏览器卡顿的问题
* 使用setTimeout index.html <html> <head> <meta charset="UTF-8"> <title ...
- JS函数节流和函数防抖问题分析
问题1:如果实现了dom拖拽功能,但是在绑定拖拽事件的时候发现每当元素稍微移动一点便触发了大量的回调函数,导致浏览器直接卡死,这个时候怎么办? 问题2:如果给一个按钮绑定了表单提交的post事件,但是 ...
- underscore.js中的节流函数debounce及trottle
函数节流 throttle and debounce的相关总结及想法 一开始函数节流的使用场景是:放止一个按钮多次点击多次触发一个功能函数,所以做了一个clearTimeout setTimeou ...
随机推荐
- CentOS 6 下升级安装Mysql 5.5 完整步骤
使用系统CentOS 6.2本来已经系统自带安装了mysql 5.1,但是奈何5.1不支持utf8mb4字符集(详见:http://blog.csdn.net/shootyou/article/det ...
- 基于Websocket+SpringMVC4推送部标Jt808终端报警(转)
原文地址:http://www.jt808.com/?p=1263 在开发部标监控平台的时候,我们要及时的将部标终端报警推送到web界面上,以弹窗的形式提供给用户显示,要将报警显示在界面上,部标808 ...
- [elk]Mutate filter plugin增删改查字段
Mutate filter plugin参考: https://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html ...
- <LeetCode OJ> 234. Palindrome Linked List
Total Accepted: 40445 Total Submissions: 148124 Difficulty: Easy Given a singly linked list, determi ...
- 基于Redis实现延时队列服务
背景 在业务发展过程中,会出现一些需要延时处理的场景,比如: a.订单下单之后超过30分钟用户未支付,需要取消订单 b.订单一些评论,如果48h用户未对商家评论,系统会自动产生一条默认评论 c.点我达 ...
- 一款基于css3鼠标经过圆形旋转特效
今天给大家分享一款基于css3鼠标经过圆形旋转特效.当鼠标经过的时候图片边框颜色旋转,图片显示详情.该实例适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲游.搜狗 ...
- springJDBC实现查询
其实在Spring这个框架中,提供了一些对JDBC访问数据库的封装,其中JdbcTemplate就是一个很好用的类,下面来 演示一下这个类的一些用法.首先需要导入commons-logging.jar ...
- IOS设备信息与机型对照表
http://blog.csdn.net/olsQ93038o99S/article/details/78374343 参考别人的文章吧....
- windbg的使用
1. set 1.1. 设置Symbol file path file->symbol file path, 如: D:\***\TestProject\pdb 1.2 设置source ...
- python的post请求抓取数据
python通过get方式,post方式发送http请求和接收http响应-urllib urllib2 python通过get方式,post方式发送http请求和接收http响应-- import ...