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 ...
随机推荐
- Linux 内存中的Cache,真的能被回收么?
您真的了解Linux的free命令么? 在Linux系统中,我们经常用free命令来查看系统内存的使用状态.在一个RHEL6的系统上,free命令的显示内容大概是这样一个状态: 这里的默认显示单位是k ...
- windows 和 linux 安装 scrapyd 出现Not a directory site-packages/scrapyd-1.0.1-py2.7.egg/scrapyd/txapp.py
1 这是因为 scrapyd安装的时候没有 解压 对应的 egg而导致的文件找不到的错误. 2 解决的方法,找到 scrapyd-1.0.1-py2.7.egg 解压缩 里面 有一个 scrapy ...
- Coreseek:第一步配置文件
Windows操作系统下:mysql数据源配置:(相应coreseek-3.2.13-win32/etc/csft_mysql.conf) #源定义 source mysql { type = mys ...
- python模块之XlsxWriter 详解
Xlsx是python用来构造xlsx文件的模块,可以向excel2007+中写text,numbers,formulas 公式以及hyperlinks超链接. 可以完成xlsx文件的自动化构造,包括 ...
- VS中C#读取app.config数据库配置字符串的三种方法(转)
关于VS2008或VS2005中数据库配置字符串的三种取法 VS2008建立Form程序时,如果添加数据源会在配置文件 app.config中自动写入连接字符串,这个字符串将会在你利用DataSet, ...
- 华为/中兴 3G 模块的调试
1 检查/etc/init.d/pppd『红颜色的使上电自动上网注册(如果没有红颜色的语句),请添加』 #!/bin/sh#DAEMON=/usr/sbin/pppdPIDFILE=/var/run/ ...
- HeadFisrt 设计模式03 装饰者
类应该对扩展开放, 对修改关闭. 所谓装饰者模式, 是指用其他的类来装饰某个类, 装饰者说白了就是使用 has-a 来代替 is-a 隐喻 咖啡店, 有很多种咖啡, 咖啡里还要增加一些 milk, 面 ...
- C++ 类的抽象初练
/* 某商店经销一种货物,货物的购进和卖出以箱为单位,各箱的重量不一样, 因此商店需要目前库存的总重量. 现在用c++模拟商店货物购进和卖出的情况 */ #include<iostream> ...
- 009杰信-创建购销合同Excel报表系列-2-建立购销合同(增删改查)
前面一篇文章已经分析好了数据库的表,这篇文章针对购销合同表做一个增删改查. 和之前的表的增删该查类似. 项目结构如下:
- 002杰信-陌生的maven-web项目整改成我们熟悉的Web架构;classpath的含义;ssm框架的整合;junit测试
这篇博客的资源来源于创智播客,先在此申明.这篇博客的出发点是jk项目,传智的做法是Maven的web模板生成的,但是这样子的结构目录与我们熟知的Web项目的结构目录相差很大,所以要按照我们熟知的项目结 ...