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() 分析与优化的更多相关文章

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

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

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

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

  3. [概念] js的函数节流和throttle和debounce详解

    js的函数节流和throttle和debounce详解:同样是实现了一个功能,可能有的效率高,有的效率低,这种现象在高耗能的执行过程中区分就比较明显.本章节一个比较常用的提高性能的方式,通常叫做&qu ...

  4. JS的函数节流(throttle)

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

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

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

  6. 函数节流throttle和防抖debounce

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

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

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

  8. JS函数节流和函数防抖问题分析

    问题1:如果实现了dom拖拽功能,但是在绑定拖拽事件的时候发现每当元素稍微移动一点便触发了大量的回调函数,导致浏览器直接卡死,这个时候怎么办? 问题2:如果给一个按钮绑定了表单提交的post事件,但是 ...

  9. underscore.js中的节流函数debounce及trottle

    函数节流   throttle and debounce的相关总结及想法 一开始函数节流的使用场景是:放止一个按钮多次点击多次触发一个功能函数,所以做了一个clearTimeout setTimeou ...

随机推荐

  1. unity, destroy gameObject & destroy all children

    一,destroy gameObject 删除名为xxx的gameObject 错误方法1: Destroy(xxx); 以上方法之所以错误,是因为Destroy在下一帧才生效,而在本帧之内xxx还存 ...

  2. .atitit.web 推送实现解决方案集合(3)----dwr3 Reverse Ajax

    .atitit.web 推送实现解决方案集合(3)----dwr3 Reverse Ajax 1. 原理实现 1 2. Page  增加配置,增加回调函数dwr.engine.setActiveRev ...

  3. Atitit.故障排除系列-----apache 不能启动的排除

    Atitit.故障排除系列-----apache 不能启动的排除 能直接使用cli启动httpd   ,,详细打印出信息.. C:\Users\ASIMO>"C:\wamp\apach ...

  4. OpenCV3+Python3

    OpenCV3计算机视觉Python语言实现笔记 图像处理与OpenCV Python3与OpenCV3.3 图像处理 OpenCV文摘 基于Python3 + OpenCV3.3.1的远程监控程序 ...

  5. sql row_number 用法

    自己研究了一下RowNum ,发现这样的分页挺清晰的 --第几页,一页多少行declare @PageIndex int,@PageMax intset @PageIndex =1set @PageM ...

  6. 微信小程序 - toptip效果

    在Page顶部下滑一个提示条 , 代码见 /mixins/UIComponent.js ,其中的self 可以认为是微信小程序的Page对象 效果: 默认2秒展示,上移动画隐藏 /** * 展示顶部 ...

  7. c libghttp ghttp 库使用指南

    libghttp是一个很好用的 http 库,能够轻松地实现同步和异步的HTTP请求 目录 [隐藏]  1 安装 2 GET示例 3 POST示例 4 相关函数 5 艺搜参考 安装 库文件下载: 在6 ...

  8. Jquery动态添加 删除 操作实现

    这是gridView为空数据时显示的表头 下面直接填代码: function Add() { //动态添加行 $("#gridCustomerView").append(" ...

  9. 29Spring_Autowriter的一些疑惑(很重要)

    我用一个Autowriter去注解一个属性,而且我没有在Spring的配置文件中的bean.xml中注册bean(<bean id=""...);那么这个注解有用吗?答案是不 ...

  10. multimap 小例子

    场景: 按DDX值倒序取前十的板块代码,用 map<float, string, greater<float> > mapBKDDX; 存储时,相同DDX值的板块只能存储第一个 ...