Skip to content

Latest commit

 

History

History
127 lines (106 loc) · 2.75 KB

节流.md

File metadata and controls

127 lines (106 loc) · 2.75 KB

节流

触发时间内只执行一次

time计算

特点:事件立刻执行,停止触发后没有办法再执行事件

function throttle(fn, wait) {
  var pre = 0
  
  return function () {
    var context = this
    var args = arguments
    var now = +new Date()
   
    if (now - pre > wait) {
       pre = now
       fn.apply(context, args)
    }
  }
}

setTimeout

特点:事件会在 n 秒后第一次执行,停止触发后依然会再执行一次事件

function throttle(fn, wait) {
  var timeout
  
  return function() {
    var context = this
    var args = arguments
    if (!timeout) {
      timeout = setTimeout(function() {
        timeout = null
        fn.apply(context, args)
      }, wait)
    } 
  }
}

组合

特点:事件立刻执行,停止触发后依然会再执行一次事件

function throttle(fn, wait) {
  var timeout, context, args, now
  var preTime = 0
  
  var later = function() {
    preTime = +new Date()
    timeout = null
    fn.apply(context, args)
  }
  
  var throttled = function() {
    context = this
    args = arguments
    now = +new Date()
    var remainTime = wait - (now - preTime)
    
    if (remainTime <= 0) {
      if (timeout) {
        clearTimeout(timeout)
        timeout = null
      } 
      preTime = now
      fn.apply(context, args)
    } else if (!timeout) {
      timeout = setTimeout(later, wait)
    }
  }
  
  return throttled
}

优化

传入第三个参数options(注意两者不可同时设置为false)

  1. leading:是否第一次执行
  2. trailing:是否停止触发的回调

如果同时设置的话,比如当你将鼠标移出的时候。因为 trailing 设置为 false,停止触发的时候不会设置定时器,所以只要再过了设置的时间,再移入的话,就会立刻执行

function throttle(fn, wait, options) {
  var timeout, now, context, args
  var preTime = 0
  
  var later = function() {
    preTime = options.leading === false ? 0 : +new Date()
    timeout = null
    fn.apply(context, args)
  }
  
  var throttled = function() {
    context = this
    args = arguments
    now = +new Date()
    
    if (preTime === 0 && options.leading === false) preTime = now 
    
    var remainTime = wait - (now - preTime)
    
    if (remainTime <= 0) {
      if (timeout) {
        clearTimeout(timeout)
        timeout = null
      }
      preTime = now
      fn.apply(context, args)
    } else if (!timeout && options.trailing === true) {
      timeout = setTimeout(later, wait)
    }
  }
  
  throttled.cancel = function() {
    clearTimeout(timeout)
    timeout = null
    preTime = 0
  }
  
  return throttled
}

参考

JavaScript专题之跟着 underscore 学节流