自定义工具函数库(一) 函数相关
最终仓库:utils: 自定义工具库
之前在哔哩哔哩看的视频的笔记。整理了一下。
1.1 call 函数封装实现
原理:为传入的 obj 添加临时方法,然后去调用这个临时方法,这样子,这个方法的this
就会指向调用它的对象了,最后还需要把临时方法删除掉。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function call(fn, obj, ...args) { if (obj === undefined || obj === null) { obj = globalThis; }
obj.temp = fn;
let result = obj.temp(...args);
delete obj.temp;
return result; }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function add(a, b) { console.log(this); return a + b + this.c; }
let obj = { c: 3, };
window.c = 100;
console.log(call(add, obj, 1, 2)); console.log(obj);
console.log(call(add, null, 1, 2));
|
1.2 apply 函数
原理:和 call
函数一样,就只是第三个参数是数组,而不是多个参数而已,所以不需要使用扩展运算符 ...
1 2 3 4 5 6 7 8 9 10 11 12 13
| function apply(fn, obj, args) { if (obj === undefined || obj === null) { obj = globalThis; } obj.temp = fn;
let result = obj.temp(...args);
delete obj.temp;
return result; }
|
1.3 bind 函数
需要依赖自定义 call 函数或内置 call 函数
这个函数功能和 call
函数一样,所以可以调用内置的 call
函数来实现,当然也可以调用自定义版本的。
不同的是,返回是一个函数,而不是立即调用。而且在调用 bind
时可以传参,调用返回的函数也可以传参,只是如果传两次参数,则只有第一次的参数会起作用
1 2 3 4 5 6
| function bind(fn, obj, ...args1) { return function (...args2) { return fn.call(obj, ...args1, ...args2); }; }
|
测试用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>函数封装实现</title> <script src="./bind.js"></script> </head>
<body> <script> function add(a, b) { console.log(arguments); return a + b + this.c; }
let obj = { c: 3, };
window.c = 100;
const fn1 = bind(add, obj, 3, 4); console.log(fn1());
const fn2 = bind(add, obj, 3, 4); console.log(fn2(5, 6));
const fn3 = bind(add, obj); console.log(fn3(5, 6));
const fn4 = bind(add, null, 3, 4); console.log(fn4());
</script> </body> </html>
|
1.4 函数节流和函数防抖
- 事件频繁触发可能造成问题
- 一些浏览器事件如
window.onresize
、 window.mousedown
等,触发频率高,会造成界面卡顿
- 向后台发送请求,频繁触发的话,对服务器会造成不必要的麻烦
解决方案:通过函数节流和函数防抖限制事件处理函数的频繁调用
1.4.1 函数节流(throttle)
场景:
- resize 事件(窗口调整)
- scroll 事件(页面滚动)
- mousemove 事件(拖拽功能)
- click 事件(疯狂点击点击)
语法: throttle(callback, wait)
功能:创建一个节流函数,在 wait 毫秒内最多执行 callback
一次
实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| function throttle(callback, wait) { let start = 0;
return function (event) { let now = Date.now();
if (now - start >= wait) { callback.call(this, event);
start = now; } }; }
|
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>函数封装实现</title> <style> body { height: 2000px; background-color: skyblue; } </style> <script src="./throttle.js"></script> </head>
<body> <script>
window.addEventListener( "scroll", throttle(function () { console.log(this.scrollY); }, 500) ); </script> </body> </html>
|
1.4.2 函数防抖(debounce)
- 在函数需要频繁触发时:在规定时间内,只让最后一次生效,前面的不生效
- 适合多个事件一次相应的情况
场景:输入框实时搜索联想(keyup / input)
语法: debounce(callback, wait)
功能:创建一个防抖动函数,该函数会从上一次被触发后,延迟 wait
毫秒后调用 callback
如果触发一次,还没过 wait
毫秒,再次触发,那么又得重新计时,依此类推,直到延迟 wait
毫秒后才调用 callback
(即频繁触发时,只让最后一次生效)
实例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function debounce(callback, time) { let timer = null;
return function (e) { clearTimeout(timer);
timer = setTimeout(() => { callback.call(this, e); }, time); }; }
|
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>函数封装实现</title> <script src="./debounce.js"></script> </head>
<body> <input type="text" /> <script> const input = document.querySelector("input");
input.onkeydown = debounce((e) => { console.log(e.keyCode); }, 1000); </script> </body> </html>
|
尚硅谷 Web 前端自定义工具函数库视频教程_哔哩哔哩_bilibili