浅谈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. 【poj1741】 Tree

    http://poj.org/problem?id=1741 (题目链接) 题意 给出一个n个节点的带权树,求树上距离不超过K的所有点对的个数. solution  点分治裸题.所谓的点分治,就是对于 ...

  2. Windows、Linux下文件操作(写、删除)错误的产生原因、及解决方法

    catalog . 引言 . Linux平台上涉及的File IO操作 . Windows平台上涉及的File IO操作 0. 引言 本文试图讨论在windows.linux操作系统上基于C库进行文件 ...

  3. iOS开发者账号配置进行设备调试

    PS:我特么写了这么久,居然图片消失了,服了. 问题一:苹果开发者账号类型: 分为三种:个人的(99美金一年).组织的(99美金一年)和企业账号(299美金一年),申请时需要信用卡,可以找淘宝的代理申 ...

  4. python中isort的使用

    是一个使import 列表更美观的工具包,官方例子如下: before from my_lib import Object print("Hey") import os from ...

  5. Codeforces Round #346 (Div. 2)E - New Reform(DFS + 好题)

    E. New Reform time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  6. CSS3-column分栏

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

  7. nginx的在linux系统中的安装

    1 nginx安装环境 nginx是C语言开发,建议在linux上运行,本教程使用Centos6.5作为安装环境. n  gcc 安装nginx需要先将官网下载的源码进行编译,编译依赖gcc环境,如果 ...

  8. DIY(码表)制作实验

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

  9. centos6.4 搭建svn服务器

    SVN作为新一代代码版本管理工具,有很多优点,管理方便,逻辑明确,安全性高,代码一致性高.SVN数据存储有两种方式,BDB(事务安全表类型)和FSFS(一种不需要数据库的存储系统),为了避免在服务器连 ...

  10. throw er; // Unhandled 'error' event

    events.js:72 throw er; // Unhandled 'error' event ^Error: listen EADDRINUSE at errnoException (net.j ...