防抖、节流
防抖(debounce)
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
function debounce(fn, wait) {let timeout;return function () {let context = this;let args = arguments;if (timeout) clearTimeout(timeout);timeout = setTimeout(() => {fn.apply(context, args);}, wait);}}
function debounce(fn, wait) {let timeout;return function () {let context = this;let args = arguments;if (timeout) clearTimeout(timeout);let callNow = !timeout;timeout = setTimeout(() => {timeout = null;}, wait);if (callNow) fn.apply(context, args);}}
function debounce(fn, wait, immediate = true) {let timeout;return function () {let context = this;let args = arguments;if (timeout) clearTimeout(timeout);if (immediate) {let callNow = !timeout; // 根据 timer 是否为 null 来判断是否要执行 fn.timeout = setTimeout(() => {timeout = null;}, wait);if (callNow) fn.apply(context, args);} else {timeout = setTimeout(() => {fn.apply(context, args);}, await)}}}
节流(throttle)
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
function throttle (fn, wait) {let previous = 0;return function () {let now = Date.now();let context = this;let args = arguments;/* 返回函数一直在被调用,但是只有 now - previoust > wait 时,才会调用 fn */if (now - previous > wait) {fn.apply(context, args);previous = now;}}}
function throttle (fn, wait) {let timeout;return function () {let context = this;let args = arguments;if (!timeout) {timeout = setTimeout(() => {timeout = null;fn.apply(context, args);}, wait);}}}
function throttle(fn, wait, immediate = true) {if (immediate) {// 注意: varvar previous = 0;} else {// 注意: varvar timeout;}return function () {let context = this;let args = arguments;if (immediate) {let now = Date.now(); // 获取当前时间戳if (now - previous > wait) {fn.apply(context, args);previous = now;}} else if (!immediate) {if (!timeout) {timeout = setTimeout(() => {timeout = null;fn.apply(context, args);}, wait);}}}}
function throttle(fn, wait = 500) {let previous = 0let timer = nullreturn function anonymous(...args) { // 匿名函数const now = Date.now()const remaining = wait - (now - previous)if(remaining <= 0) {clearTimeout(timer)timer = nullprevious = nowfn.call(this, ...args)} else if(!timer) {// 若间隔时间小于 500ms,此时只过去了 5ms ,那就需要再过 450ms 后再执行。// 也就说,当前时间还没有超过设定的节流时间,那就需要知道需要等多久才可执行,此时设置一个定时器来定时执行。timer = setTimeout(() => { // 注意是箭头函数clearTimeout(timer)timer = nullprevious = Date.now()fn.call(this, ...args)}, remaining)}}}
