浅谈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. 【csuoj1014】 西湖三人行

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1014 (题目链接) 题意 从无向图图上一点到达另一点,可以步行,搭公交或者是打的,不同的交通方式花 ...

  2. sql查找最后一个字符匹配

    DECLARE @str AS VARCHAR(25)='123_234_567' select substring(@str,1,LEN(@str)-CHARINDEX('_',reverse(@s ...

  3. poj3675 求多边形与圆的面积交

    题意:给出多边形的顶点坐标.圆的圆心坐标和半径,求面积交 sol:又是模板题啦= = 注意poj的C++好像认不出hypot函数,要稍微改写一下. hypot(double x,double y):即 ...

  4. 对iOS中Delegate的理解

    首先 协议protocol 和委托delegate 是两个完全不同的概念  放在一起说 是因为我们总是在同一个头文件里看到它们: 首先解释一下什么是委托 :举个例子 ,我工作的时候给你打电话,让你帮我 ...

  5. centos6.5下安装mysql

    http://www.centoscn.com/mysql/2014/0812/3481.html 1.使用yum命令安装mysql [root@bogon ~]#  yum -y install m ...

  6. CSS3中的animation动画

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  7. sql 列转行 实例

    select * from dbo.orders  group by  custid  with cube    select custid ,row_number() over(order by e ...

  8. Win7、Ubuntu双系统正确卸载Ubuntu系统

    正确的删除ubuntu方法如下: 第1步,修复MBR 1.进入win7,下载个软件MbrFix,放在C:windowssystem32文件夹中 2.点击开始>所有程序>附件>命令提示 ...

  9. /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题

    一.MD(d).MT(d)编译选项的区别 1.编译选项的位置 以VS2005为例,这样子打开: 1)         打开项目的Property Pages对话框 2)         点击左侧C/C ...

  10. 10月21日上午MySQL数据库学习内容复习

    1.创建数据库create database 数据库名称删除数据库drop database 数据库名称 2.创建表create table 表名(列名 类型(长度) 自增长 主键 非空,)自增长:a ...