浅谈javascript函数节流

什么是函数节流?

函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等等事情,那么这时候窗口缩放的时候,有可能连续发多个请求,这并不是我们想要的,或者是说我们常见的鼠标移入移出tab切换效果,有时候连续且移动的很快的时候,会有闪烁的效果,这时候我们就可以使用函数节流来操作。大家都知道,DOM的操作会很消耗或影响性能的,如果是说在窗口缩放的时候,为元素绑定大量的dom操作的话,会引发大量的连续计算,比如在IE下,过多的DOM操作会影响浏览器性能,甚至严重的情况下,会引起浏览器崩溃的发生。这个时候我们就可以使用函数节流来优化代码了~

函数节流的基本原理:

使用一个定时器,先延时该函数的执行,比如使用setTomeout()这个函数延迟一段时间后执行函数,如果在该时间段内还触发了其他事件,我们可以使用清除方法 clearTimeout()来清除该定时器,再setTimeout()一个新的定时器延迟一会儿执行。

我们先来看一个简单的window.resize的demo例子,比如我先定义一个全局变量count=0;当我触发一次window.resize的时候,该全局变量count++; 我们来看看在控制台中打印出count的效果;JS代码如下:

var count = 0;
window.onresize = function(){
count++;
console.log(count);
}

执行截图效果如下:

如上resize的代码,简单的缩放一次就打印出多次,这并不是我们想要的效果,这是简单的测试,那如果我们换成ajax请求的话,那么就会缩放一次窗口会连续触发多次ajax请求,下面我们试着使用函数节流的操作试试一下;

函数节流的第一种方案封装如下:

function throttleFunc(method,context){
clearTimeout(method.tId);
method.tId = setTimeout(function(){
method.call(context);
},100);
}

我们再来封装一下窗口缩放的demo

var count = 0;
function myFunc() {
count++;
console.log(count);
}
window.onresize = function(){
throttleFunc(myFunc);
}
function throttleFunc(method,context){
clearTimeout(method.tId);
method.tId = setTimeout(function(){
method.call(context);
},100);
}

如上代码,我们再来看看效果,窗口缩放和放大效果会看到,只执行了一次;打印了一次。

上面的代码使用一个定时器每隔100毫秒执行一次;

我们也可以使用闭包的方法对上面的函数进行再封装一下;

函数节流的第二种封装方法如下:

function throttle(fn, delay){
var timer = null;
return function(){
var context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
fn.apply(context, args);
}, delay);
};
};

上面第二种方案是使用闭包的方式形成一个私有的作用域来存放定时器timer,第二种方案的timer是通过传参数的形式引入的。

调用demo代码如下:

var count = 0;
function myFunc() {
count++;
console.log(count);
}
var func = throttle(myFunc,100);
window.onresize = function(){
func();
}
function throttle(fn, delay){
var timer = null;
return function(){
var context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
fn.apply(context, args);
}, delay);
};
};

函数节流的基本思想是:就是想让一个函数不要执行的太频繁,减少一些过快的来节流函数,比如当我们改变窗口缩放的时候,浏览器的间隔有可能是16ms,这是浏览器自带的时间间隔,我们无法改变,而我们通过节流的方式可以试着改变一下这个间隔,尽量稍微延长下这个调用时间,因此我们可以封装如下函数:

函数节流的第三种封装方法

function throttle3(fn,delay,runDelay){
var timer = null;
var t_start;
return function(){
var context = this,
args = arguments,
t_cur = new Date();
timer && clearTimeout(timer);
if(!t_start) {
t_start = t_cur;
}
if(t_cur - t_start >= runDelay) {
fn.apply(context,args);
t_start = t_cur;
}else {
timer = setTimeout(function(){
fn.apply(context,args);
},delay);
}
}
}

调用demo如下:

var count = 0;
function myFunc() {
count++;
console.log(count);
}
var func = throttle3(myFunc,50,100);
window.onresize = function(){
func();
}
function throttle3(fn,delay,runDelay){
var timer = null;
var t_start;
return function(){
var context = this,
args = arguments,
t_cur = new Date();
timer && clearTimeout(timer);
if(!t_start) {
t_start = t_cur;
}
if(t_cur - t_start >= runDelay) {
fn.apply(context,args);
t_start = t_cur;
}else {
timer = setTimeout(function(){
fn.apply(context,args);
},delay);
}
}
}

上面的第三个函数是封装后的函数,有三个参数,我们可以自己设置触发事件的时间间隔,则意味着,如上代码50ms连续调用函数,后一个调用会把前一个调用的等待处理掉,但每隔100ms会至少执行一次,具体使用哪一种方式只要看自己的权衡,但是我个人觉得第二种封装函数的方式够我们使用的,当然据说第三种方式性能更好~

浅谈javascript函数节流的更多相关文章

  1. [转载]浅谈JavaScript函数重载

     原文地址:浅谈JavaScript函数重载 作者:ChessZhang 上个星期四下午,接到了网易的视频面试(前端实习生第二轮技术面试).面了一个多小时,自我感觉面试得很糟糕的,因为问到的很多问题都 ...

  2. 再谈javascript函数节流

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

  3. [转]浅谈javascript函数劫持

    转自:Ph4nt0m Security Team 这么多年了,现在学习依然还是有很多收货,向前辈致敬.转载一方面是自己存档一份,另一方面是让更多喜欢安全的人一同学习. ================ ...

  4. 浅谈JavaScript 函数作用域当中的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的. 例如 : message = "hello JavaScript ! " ...

  5. 浅谈javascript函数,变量声明及作用域

    javascript函数跟变量的声明.作用域这些概念网上都已经讲烂了. 这里写个博客,也相当于做个笔记. 变量声明 首先看个例子: var globalVar = "gv"; fu ...

  6. 浅谈javascript函数执行过程

    javascript函数执行过程: 1. 为函数创建一个执行环境 2. 复制函数的 [[scopes]] 属性中的对象构建起执行环境的作用链域 3. 创建函数活动对象并推入执行环境作用链域的前端 4. ...

  7. 浅谈JS函数节流及应用场景

    说完防抖,下面我们讲讲节流,规矩就不说了,先上代码: <!DOCTYPE html> <html lang="en"> <head> <m ...

  8. 浅谈JavaScript函数

    JavaScript作为一种基于对象(非严格面向对象)的语言,函数在JS中的地位非同一般:用函数声明类和对象.甚至函数本身也是对象. 一.函数的三种声明方式辨析. 1.function命令 funct ...

  9. 浅谈JavaScript函数重载

    上个星期四下午,接到了网易的视频面试(前端实习生第二轮技术面试).面了一个多小时,自我感觉面试得很糟糕的,因为问到的很多问题都很难,根本回答不上来.不过那天晚上,还是很惊喜的接到了HR面电话.现在HR ...

随机推荐

  1. SQL Server数据同步的研究(单向/双向)

    思路: 1.做中间件(简单:定时采集:复杂:分布式,订阅中心的形式,如微信的中间件:https://github.com/tencent-wechat/phxsql) 2.采用触发器的形式,有数据触发 ...

  2. Scala可变长度参数

    可变长度参数 Scala 允许你指明函数的最后一个参数可以是重复的.这可以允许客户向函数传入可变长度参数列表.想要标注一个重复参数,在参数的类型之后放一个星号.例如: scala> def ec ...

  3. HTML之:fieldset——一个不常用的HTML标签

    2016年4月14日17:10:02记录 一个不常用的HTML标签fieldset,不过我觉得比较有意思,其语法如下: <fieldset><legend>fieldset名称 ...

  4. angular ui-router 缓存问题

    在个别情况下 $state.go()路径和参数完全相同的时候页面因为缓存问题可以直接跳转,但是不能重新获取数据 通过路由参数可以解决 路由 .state('app.***.***', { url: ' ...

  5. DIY(码表)制作实验

    代码: #include<reg52.h>typedef unsigned char u8;typedef unsigned int  u16;/********端口定义********* ...

  6. SVM支持向量机的高维映射与核函数-记录毕业论文2

    上一篇博客将了在数据集线性可分的情况下的支持向量机,这篇主要记录如何通过映射到高维解决线性不可分的数据集和如何通过核函数减少内积计算量的理论思想. [5]径向基函数的核函数:https://www.q ...

  7. EasyUI学习笔记之panel

    <easyUI panel 属性:> <!--引入easyUI panel 组件 设置宽,高,定义标题(默认在左上角),设置图标iconCls:'icon-ok',引入工具tools ...

  8. NLTK中文语料库sinica_treebank

    http://www.hankcs.com/program/python/nltk-chinese-corpus-sinica_treebank.html NLTK包含Sinica (中央研究院)提供 ...

  9. ubuntu分区

    参考网址:http://jingyan.baidu.com/article/60ccbceb18624464cab197ea.html

  10. Java Connection.setAutoCommit

    Java setAutoCommit 默认为true,即每条SQL语句在各自的一个事务中执行. 很多时候需要有多个操作在一个事务执行,如循环插入,此时可在插入开始前设置 conn.setAutoCom ...