引子:昨天面试时面试官问了如何实现一个固定导航栏,在我答完后面试官问我可能存在哪些问题,如何优化?

这个问题我答得不太好,但现在回想起来应该有两个问题:

1. 把 fixbar元素 position:fixed 之后,它将脱离文档流,后面的元素将会跟上,这可能会形成一个闪烁,解决方法是跟随的元素设置 margin-top 为 fixbar 元素的高度,或者替换上一个等高的元素,这点面试时候没有描述出来。

2. 就是这篇博文主要内容 ”函数节流“,英文名 throttle 函数,在一些库,如underscore中有其实现,

主要思想是:对于非常频烦发射的事件,可以设置一定时间的”缓冲“,在这一定的时间内只执行最后一次时间的响应函数。

例如对于 窗口的滚动条拖动,onscroll时间是非常频繁发射的,如果每次发射都执行事件处理函数,那么将会增加浏览器负担,这时如果200ms(只是举例)执行一次,那么性能上将有所改善,效果上也能接受,当然实际应用需要二者找到一个平衡。

JQuery作者 John Resig 在2011年的一篇博文中提出了这个问题的最佳实践方法,请点击原文查看。代码如下:

    var outerPane = $details.find(".details-pane-outer"),
didScroll = false; $(window).scroll(function() {
didScroll = true;
}); setInterval(function() {
if ( didScroll ) {
didScroll = false;
// Check your page position and then
// Load in more results
}
}, 250);

通俗地大家把它称为 函数节流/事件稀释, 在 underscore 中,也有这个实现:

throttle_.throttle(function, wait, [options]) 
Creates
and returns a new, throttled version of the passed function, that, when
invoked repeatedly, will only actually call the original function at
most once per every waitmilliseconds. Useful for rate-limiting events that occur faster than you can keep up with.

By default, throttle will execute the function as soon as you call it for the first time, and, if you call it again any number of times during the wait period, as soon as that period is over. If you'd like to disable the leading-edge call, pass {leading: false}, and if you'd like to disable the execution on the trailing-edge, pass 
{trailing: false}.

var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);

以下是具体的实现代码:

 _.throttle = function(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function() {
var now = _.now();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
};

参考链接:

Learning from Twitter

underscore.js

JavaScript 频繁发射事件处理的优化 --- 函数节流/事件稀释的更多相关文章

  1. JavaScript性能优化之函数节流(throttle)与函数去抖(debounce)

    函数节流,简单地讲,就是让一个函数无法在很短的时间间隔内连续调用,只有当上一次函数执行后过了你规定的时间间隔,才能进行下一次该函数的调用. 函数节流的原理挺简单的,估计大家都想到了,那就是定时器.当我 ...

  2. javascript 函数节流 throttle 解决函数被频繁调用、浏览器卡顿的问题

    * 使用setTimeout index.html <html> <head> <meta charset="UTF-8"> <title ...

  3. JavaScript性能优化技巧之函数节流

    函数节流技术的主要思路是,通过一个定时器,阻断连续重复的函数调用.对于我们自己内部使用的函数,这通常意义不大,也不推荐使用这个技术,它可能会丢失对某些数据的处理.但是对于在用户界面调用的函数,却非常有 ...

  4. 浅谈javascript函数节流

    浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...

  5. JavaScript函数节流与函数去抖

    介绍 首先解释一下这两个概念: 函数节流(throttle):是让一个函数无法在很短的时间间隔内连续调用,当上一次函数执行后过了规定的时间间隔,才能进行下一次该函数的调用. 函数去抖(debounce ...

  6. 浅谈javascript的函数节流

    什么是函数节流? 介绍前,先说下背景.在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(其核心就是绑定mousemove),这种事件有一个特点,就是用户不必特地捣乱,他在 ...

  7. 深入理解javascript函数进阶系列第三篇——函数节流和函数防抖

    前面的话 javascript中的函数大多数情况下都是由用户主动调用触发的,除非是函数本身的实现不合理,否则一般不会遇到跟性能相关的问题.但在一些少数情况下,函数的触发不是由用户直接控制的.在这些场景 ...

  8. js前端性能优化之函数节流和函数防抖

    前言:针对一些会频繁触发的事件如scroll.resize,如果正常绑定事件处理函数的话,有可能在很短的时间内多次连续触发事件,十分影响性能 节流: 节流:使得一定时间内只触发一次函数. 它和防抖动最 ...

  9. javaScript函数节流与函数防抖

    javaScript函数节流与防抖之区别 函数防抖(debounce)与函数节流(throttle)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟.假死或卡顿 ...

随机推荐

  1. 将Linux(ubuntu)安装到U盘上,实现即插即用

    说明: 本教程是说明如何将ubuntu系统安装到U盘上(也就是把U盘当做电脑的硬盘),可以实现U盘插到任何电脑上都能够在实体机上运行ubuntu系统,而且所有的运行配置都能被保存,相当于随身携带的一个 ...

  2. python 使用多线程进行并发编程/互斥锁的使用

    import threading import time """ python的thread模块是比较底层的模块,python的threading模块是对thread做了 ...

  3. 软件测试人员需要掌握的linux命令(一)

    有些技能可以事半功倍,熟练的使用这些命令可以提高工作效率,并且结合这些命令对测试过程中遇到的问题进行一些初步的定位. 一:目录与文件操作: ls 使用权限:所有人功能 : 显示指定工作目录下之内容(列 ...

  4. Window安装Erlang环境

    最近学习RabbitMQ,下载rabbitmq-server后,安装提示,需要erlang环境,接着又下载erlang安装包. 仅在这里提供下安装文件和环境配置方法. 1.rabiitmq-serve ...

  5. RawConfigParser 与 ConfigParser ——Python的配件文件读取模块

    一般情况都是使用ConfigParser这个方法,但是当我们配置中有%(filename)s这种格式的配置的时候,可能会出现以下问题: configparser.InterpolationMissin ...

  6. Split()[1]中的[1]是什么意思

    split()方法是将指定字符串按某指定的分隔符进行拆分,拆分将会形成一个字符串的数组并返回 如:string str = "aa.bb.cc.dd"; string[] strA ...

  7. 如何开始DDD

    在开始DDD之前,你需要了解DDD的一些基础知识,聚合(AggregateRoot).实体(Entity).值对象(ValueObject),工厂(Factory),仓储(Repository)和领域 ...

  8. 树莓派安装vnc server并设置自启动

    在SSH终端输入sudo raspi-config, 这里需要打开几个选项: expand_rootfs – 将根分区扩展到整张SD卡; change_pass – 默认的用户名是pi,密码是rasp ...

  9. 这次聊聊Promise对象

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由前端林子发表于云+社区专栏 Promise是CommonJS提出的一种规范,在ES6中已经原生支持Promise对象,非ES6环境可以 ...

  10. vue router history模式开发ngnix配置

    一.前沿 现在很多用vue-router开发页面的时候,都习惯使用hash路由莫模式,如:https://xxxx/#/index/share?code=dsfsd.这种模式在做pc端开发时候挺好用的 ...