节流 and 防抖
防抖
防抖:对于短时间内连续触发的事件,防抖的含义就是让某个时间期限内,事件处理函数只执行一次。
例子:
在第一次触发事件时,不立即执行函数,而是给出一个期限值比如 200ms ,然后:
- 如果在 200ms 内没有再次触发滚动事件,那么就执行函数
- 如果在 200ms 内再次触发滚动事件,那么当前的计时取消,重新开始计时
如果短时间内大量触发同一事件,只会执行一次函数。用去除定时器的方法。
function debounce(fn, delay) {let timer = null;return function () {if (timer) {clearTimeout(timer)timer = setTimeout(fn, delay)} else {timer = setTimeout(fn, delay)}}}function showTop() {var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;console.log('滚动条位置:' + scrollTop);}window.onscroll = debounce(showTop, 1000);
如果在限定时间段内,不断触发滚动事件(比如某个用户闲着无聊,按住滚动不断的拖来拖去),只要不停止触发,理论上就永远不会输出当前距离顶部的距离。
节流
如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
function throttle(fn, delay) {let valid = true;return function () {if (!valid) {return false;}valid = false;setTimeout(() => {fn()valid = true;}, delay)}}function showTop() {var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;console.log('滚动条位置:' + scrollTop);}window.onscroll = throttle(showTop, 1000)
运行以上代码的结果是:
- 如果一直拖着滚动条进行滚动,那么会以 1s 的时间间隔,持续输出当前位置和顶部的距离。
节流还可以用时间戳实现:
function throttle(fn, delay) {let previous = 0;return function() {let now = Date.now();let context = this;let args = arguments;if (now - previous > delay) {fn.apply(context, args);previous = now;}}}
应用场景
- 搜索框input事件
- 滚动条滚动事件
页面 resize 事件,常用于需要做页面适配的时候,需要根据最终呈现的页面情况进行 dom 渲染(这种情况一般是使用防抖,因为只需要判断最后一次的变化情况)
深拷贝 and 浅拷贝
深拷贝
function deepClone(obj) {if (typeof obj !== 'object' || obj === null) return obj;let copy = {};if (Array.isArray(obj)) {copy = [];}for (const [key, value] of (Array.isArray(obj) ? obj.entries() : Object.entries(obj))) {copy[key] = deepClone(value);}return copy;}
浅拷贝
const extend = Object.assign || ((obj, ...args) => {if (args.length !== 0) {for(const source of args) {for(const [key, value] of Object.entries(source)) {obj[key] = value;}}}return obj;})
