JavaScript中函数节流的理解
函数节流的原理
函数节流,就是对会频繁触发的函数事件做一些限制,让这些函数可以在每隔一定的时间或者每次满足一定的条件下再触发。一般我们会给他起一个名字throttle。也就是节流的意思。一般这样的函数有 resize事件、ontouchmove事件等。
举个简单的例子
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>测试函数节流</title>
<style>
#container{
width: 100%;
height: 200px;
border: 1px solid #646464;
color: #000000;
}
</style>
</head>
<body >
<div id="container"></div>
</body>
<script>
function alertSomething(){
alert("您的鼠标正在移动");
};
document.getElementById("container").onmousemove = alertSomething;
</script>
</html>
上面的代码就是简单的渲染出来一个div 然后给这个div绑定了一个鼠标移动事件。但是我们在实际情况下,这种体验是不好的,因为这个事件会被十分频繁的触发。只要我们在这个div上移动鼠标就会弹出这个阻塞性的事件alert,所以我们希望每隔一定时间提醒一下“您的鼠标正在移动”。
下面写一个节流的函数throttle()。
function throttle(func){
var timer;
return function(){
var context = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
func.apply(context,args);
},1000);
}
}
然后我们修改一下页面上的代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>测试函数节流</title>
<style>
#container{
width: 100%;
height: 200px;
border: 1px solid #646464;
color: #000000;
}
</style>
</head>
<body >
<div id="container"></div>
</body>
<script>
function throttle(func){
var timer;
return function(){
var context = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
func.apply(context,args);
},1000);
}
}
function alertSomething(){
alert("您的鼠标正在移动");
};
document.getElementById("container").onmousemove = throttle(alertSomething);
</script>
</html>
下面我仔细解释一下这个节流函数。
函数利用闭包的形式存储了一个timer定时器变量,说实话我刚开始看别人在写这个节流函数的时候,也是不太容易懂,只是马马虎虎觉得是这样的,直到我亲自实现一遍,才明白。在这里建议亲自动手,丰衣足食~~
这个timer变量当然也可以写在全局作用域中,但是可能会跟全局作用域中的变量产生冲突,所以在这里用闭包的形式来提供,防止它污染全局作用域。(看好多人在这里用“污染”,我想可能是如果有很多像timer这样的变量都放在全局作用域中,到时候肯定容易与在全局作用域中常用的变量混淆。因为它毕竟只是在这个节流函数做定时器使用)。
然后就是throttle函数返回的函数了。在这个函数中,要保存好传进来的执行上下文this,和参数arguments。应为我们要注意的是setTimeout()函数中作用域是全局的,也就是setTimeout中的this指的是window,在这里这个执行上下文其实就是container对象,传入的参数就是鼠标移动这个事件的所有信息我们将这个container这个对象的鼠标移动事件函数重写成alertSomething这个函数。同时鼠标移动事件的信息也作为参数传入进去这一点也是我打印出他的相应信息后才恍然大悟,可能平时我们会理所当然的知道就是这样子的,但是为什么会这样子呢,我们知道了alertSomething这个函数的参数和执行上下文是怎么传进去的,那直接调用elementobj.onmousemove=function(){xxxxxx}这个函数的时候,上下文和参数是怎么传入进去的也应该是这样的原理吧。这是我的个人理解。
明白了上面的基本原理,我们再梳理一下节流函数发挥作用的过程:第一次调用这个节流函数的时候也就是第一次触发鼠标移动事件的时候,timer是没有的,所以clearTimeout(timer)清理的定时器也是没有的,但是等第二次触发鼠标移动事件的时候,鼠标移动事件的处理函数就是一直是throttle返回的函数了。首先会清理掉上次调用的时候的定时器,然后重新设置一个定时器。每次鼠标移动都是这样的处理过程,直到鼠标不再移动一秒钟后,定时器中的函数才被使用。
总之仔仔细细理解一下这个过程感觉真好!
但是如果我们需要自定义延迟的事件的话怎么办呢,下面我们可以再改进一下:
function throttle(func,delay){
var timer;
return function(){
var context = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
func.apply(context,args);
},delay);
}
}
function dealMouseMove(){
alert("您的鼠标正在移动");
};
document.getElementById("container").onmousemove = throttle(dealMouseMove,500);
在这里感谢 Toobug 和 flowmemo 两位大神的指正,上面函数的功能更应该称之为debounce,也即是消除抖动的意思。前端技术中常用的throttle相当于一个频率控制器,让一段时间内快速触发很多次的事件处理程序可以只触发一定的次数, 而debounce不只是减少了触发次数,而且要满足一定的条件下才会触发。两者实现方法都是差不多的,叫法不一样而已,不能将两者割裂开来。
可以参考的相关网址:http://www.css88.com/archives/4648
可以参考的相关网址:http://www.alloyteam.com/2012/11/javascript-throttle/
JavaScript中函数节流的理解的更多相关文章
- JavaScript 中函数节流和函数去抖的讲解
JavaScript 中函数节流和函数去抖的讲解 我们都知道频繁触发执行一段js逻辑代码对性能会有很大的影响,尤其是在做一些效果实现方面,或者逻辑中需要进行后端请求,更是会导致卡顿,效果失效等结果,所 ...
- Javascript中函数的四种调用方式
一.Javascript中函数的几个基本知识点: 1.函数的名字只是一个指向函数的指针,所以即使在不同的执行环境,即不同对象调用这个函数,这个函数指向的仍然是同一个函数. 2.函数中有两个特殊的内部属 ...
- JavaScript中函数是不能重载原因
以前有一次写JS插件的时候,由于后台写习惯了,妄想在JS中写重载函数,可惜不能成功,原因花了一点时间记了下来 首先要理解重载的含义:函数返回值不同或者形式参数个数不同但函数名相同的函数 JavasSc ...
- JavaScript中函数作为另一个函数的参数的时候它存在于哪个作用域
一直对函数作为参数被传递进另外一个函数理解的不是很清除.先看下这段代码吧: function test(fn){ var bar = 1; fn(); } var bar = 99; test(fun ...
- JavaScript中函数函数的定义与变量的声明<基础知识一>
1.JavaScript中函数的三种构造方式 a.function createFun(){ } b.var createFun=function (){ } c.var createFun=new ...
- JavaScript中函数的形参和实参的实现原理剖析
我们都知道JS里面参数的传递是可以不一样的,比如我们有一个函数: <script type="text/javascript"> function one(a,b,c) ...
- JavaScript中函数的调用
JavaScript中函数的调用 制作人:全心全意 在JavaScript中,函数定义后并不会自动执行,要执行一个函数需要在特定的位置调用该函数,调用函数需要创建调用语句,调用语句包含函数名称和参数. ...
- JavaScript中函数的定义
JavaScript中函数的定义 制作人:全心全意 在JavaScript中,函数是由关键字function.函数名加一组参数以及置于大括号中需要执行的一段代码定义的.定义函数的基本语法格式如下: f ...
- javascript中函数声明、变量声明以及变量赋值之间的关系与影响
javascript中函数声明.变量声明以及变量赋值之间的关系与影响 函数声明.变量声明以及变量赋值之间有以下几点共识: 1.所有的全局变量都是window的属性 2.函数声明被提升到范围作用域的顶端 ...
随机推荐
- PyTorch深度学习实践-Overview
Overview 1.PyTorch简介 PyTorch是一个基于Torch的Python开源机器学习库,用于自然语言处理等应用程序.它主要由Facebookd的人工智能小组开发,不仅能够 实现强 ...
- 写下载的时候,axios的responseType: "blob"(一定要修改)
download(data, fileName) { // window.URL.createObjectURL创建一个地址. const url = window.URL.c ...
- Node.js躬行记(16)——活动配置化
一直想将一些常规活动抽象化,制作成可配置的.原先的计划是做成拖拽的,那种可视化搭建,运营也能自己搭建页面. 这是一个美好的愿景,但是现实不允许我花太多精力去制作这样一个系统.经过权衡后,先设计成一个可 ...
- laravel 公共类json库封装
封装常用的接口响应: 创建 response.php 在app下创建如下文件下(目录及文件名可以自己设置) app/common/response.php,在内部补充如下代码: <?php /* ...
- centeros7 定时任务
crond是什么? crond 和crontab是不可分割的.crontab是一个命令,常见于Unix和类Unix的操作系统之中,用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于 ...
- ArcMap操作随记(15)
1.字段顺序的调整 [图层属性]→[字段]([高级排序]功能也在这里) 2.所谓热点地区: 本身是高值,邻居也是高值,才成为热点地区(这是操作中总结出的,但其实了解原理就很简单了,详细请查看空间自相关 ...
- 关于OAuth2.0 Authorization Code + PKCE flow在原生客户端(Native App)下集成的一点思考
写在前面 前几天看了园友的一篇文章被广泛使用的OAuth2.0的密码模式已经废了,放弃吧 被再次提起: Implicit Flow Password Grant,均已被标记为Legacy,且OAuth ...
- 使用ipmitool工具来使用串口连接远程主机
https://www.ibm.com/developerworks/cn/linux/l-ipmi/index.html ipmitool -H 9.13.2.213 -U root -P xxxx ...
- CodeUp Problem D: More is better
根据题目意思,输入的每一对A.B都是直接朋友,并且最后只会得到一个集合,该集合就是Mr Wang选择的男孩. 因此很容易写出代码,甚至不需要自己构建一个并查集,只需要使用C++的set模板,每次读入一 ...
- CF17E Palisection(manacher/回文树)
CF17E Palisection(manacher/回文树) Luogu 题解时间 直接正难则反改成求不相交的对数. manacher求出半径之后就可以差分搞出以某个位置为开头/结尾的回文串个数. ...