手写源码

手写源码

throttle 节流函数

原理

节流函数可以降低某个函数的触发频率,使其在设定的间隔内不会触发多次。常用于比如滚动事件,鼠标移动事件等处理函数的执行频率限制。

实现思路

重点在于设定间隔时间内不会多次触发,我们可以先约定在下一个间隔期执行一次(使用setTimeout)函数,然后在当前间隔期不执行函数就行。

这里我们怎么判断是不是在已执行过得函数间隔周期呢,这就需要我们记录函数执行的时间点了。

伪代码:

function throttle(fn, wait) { var 定时器, 上一次执行时间; return function () { if (第一次执行) { 上一次执行时间 = 现在; 执行函数; } if (定时器存在) return 定时器 = setTimeout(() => { 上一次执行时间 = 现在; 执行函数; 定时器 = null }, 立即执行或者延迟一个周期) } }

实现

function throttle(fn, wait) { var timer, last; return function(...args) { var now = Date.now(); if (!last) { fn.apply(this, args); last = now; return; } if (timer) return; timer = setTimeout( () => { fn.apply(this, args); last = Date.now(); timer = null; }, now - last > wait ? 0 : wait ); }; }

debounce 防抖函数

原理

防抖函数可以将多个连续触发的函数合并为一个或者两个(通常在开始或者结尾触发)。使用场景通常见于处理用户输入,在用户停顿的时候对其输入内容进行处理而不是每输入一个字就处理一次。以及在窗口改变的时候,往往我们会在窗口改变后再去做适配,而不是改变途中就开始适配,所以这里会用到防抖而不是节流函数。

实现思路

当函数被执行时,约定好一个等待间隔时间后再执行,在这期间如果函数再次被调用,那么刷新这个约定时间为当前时间的下一个等待间隔。

伪代码

function debounce(fn, wait) { var 定时器; return function (...args) { 清除定时器; 定时器 = setTimeout(() => { 执行函数; }, wait) } }

实现

function debounce(fn, wait) { var timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); }, wait); }; }

数据单向/双向绑定

原理

主要使用的是Object.defineProperty,设置数据的setter,在改变值的时候更新DOM。

实现

<input type="text" id="input">
var data = { value: 0 }; var $input = document.querySelector("#input"); var val = data.value Object.defineProperty(data, "value", { set(value) { val = value; $input.value = value; }, get() { return val; } }); $input.addEventListener("input", e => { data.value = e.target.value; });

这里实际是用到闭包去存储实际值的,可以看出data.value只是个访问代理。

上一篇 Medium每日精华
下一篇 Vue数据绑定原理之数据劫持