浅谈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. restore和recover的区别(转)

    recover和restore的区别: restore just copy the physical file, recover will consistent the database. resto ...

  2. Newton-Raphson算法简介及其R实现

    本文简要介绍了Newton-Raphson方法及其R语言实现并给出几道练习题供参考使用. 下载PDF格式文档(Academia.edu) Newton-Raphson Method Let $f(x) ...

  3. Python3导入cookielib失败

    Python 3 改成 http.cookiejar了,所以只要改成import http.cookiejar就自动导入cookiejar了,如果还是不行,就把所有的.pyc删掉试试.

  4. PHP之:PHP编程效率的20个要点

    [导读] 用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则 不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数” 用单引号 ...

  5. Tarjan_LCA

    貌似求LCA使用倍增已经可以应付掉大多数需要LCA的题了.. 但是有些时候$O(MlogN)$的复杂度就不可接受了 Tarjan_LCA对于每个询问采用离线处理 总复杂度为$O(M+N)$ 这个复杂度 ...

  6. Microsoft.Office.Interop.Excel的用法

    1)ApplicationClass ExcelApp = New ApplicationClass(); 2) 更改 Excel 标题栏: ExcelApp.Caption := '应用程序调用 M ...

  7. PHP中常用的字符串格式化函数总结

    注意:在PHP中提供的字符串函数处理的字符串,大部分都不是在原字符串上修改,而是返回一个格式化后的新字符串. 一.取出空格和字符串填补函数 空格也是一个有效的字符,在字符串中也会占据一个位置.用户在表 ...

  8. 条件运算符(?:)和 $""替代string.Format()

    1. 条件运算符(?:)根据Boolean表达式的值返回两个值之一.表达式如下: condition ? first_expression : second_expression 2. $" ...

  9. Github for Windows使用介绍

    Git已经变得非常流行,连Codeplex现在也已经主推Git.Github上更是充斥着各种高质量的开源项目,比如ruby on rails,cocos2d等等.对于习惯Windows图形界面的程序员 ...

  10. N-Gram

    N-Gram是大词汇连续语音识别中常用的一种语言模型,对中文而言,我们称之为汉语语言模型(CLM, Chinese Language Model).   中文名 汉语语言模型 外文名 N-Gram 定 ...