这是我参与「第五届青训营 」伴学笔记创作活动的第 10 天,本节课👩🏻🏫主要是讲解了hoc的定义,和它的几个例子,当然还有它的作用,我们在以后的代码中要多用hoc函数,同时对于编码风格也得改进,对于命令式和声明式这两种风格,我们要提倡使用声明式。
高阶函数
- 以函数作为参数
- 以函数作为返回值
- 常用于作为函数装饰器 如下图所示,就是一个普通的高阶函数
** 常用高阶函数 **
- Once(只触发一次)
- Throttle(节流)
- Debounce(防抖)
- Consumer / 2
- Iterative
Once实现:
#!/usr/bin/env bun
type TCallback = (data: any) => void;
interface myEventEmmitter {
on: (eventName: string, callback: TCallback) => void; // 监听事件
once: (eventName: string, callback: TCallback) => void; // 监听事件仅一次
emit: (eventName: string, data: any) => void; // 触发事件
}
class eventEmmitter implements myEventEmmitter {
events: object;
constructor() {
this.events = {};
}
on(eventName: string, callback: TCallback) {
// 事件队列不为空,就先清空下
if (!this.events) this.events = {};
// 事件名存在的话,直接push进回调;不存在,则队列只有当前的回调
if (this.events[eventName]) {
this.events[eventName].push(callback);
} else {
this.events[eventName] = [callback];
}
if (eventName !== "newListener") this.emit("newListener", eventName);
}
once(eventName: string, callback: TCallback) {
const vm = this;
// 只触发一次,便从队列中删除
function onTime(...args) {
callback.call(this, ...args);
vm.off(eventName, onTime);
}
vm.on(eventName, onTime);
}
emit(eventName: string, ...data: any) {
// 事件名存在,则触发事件
if (this.events[eventName]) {
this.events[eventName].forEach((element) => {
element.call(this, ...data);
});
}
}
off(eventName: string, callback: TCallback) {
if (this.events[eventName]) {
const index = this.events[eventName].indexOf(callback);
this.events[eventName].splice(index, 1);
}
}
}
const myEvent = new eventEmmitter();
myEvent.on("some-event", (msg) => {
console.log("i am listening", msg);
});
myEvent.once("some-event", (msg) => {
console.log("i just listen-once", msg);
});
myEvent.emit("some-event", "listen to me");
myEvent.emit("some-event", "listen to me");
Throttle代码实现:
function throttle(fn, delay) {
let now = Date.now()
return function() {
let cur = Date.now()
if (cur - now >= delay) {
now = Date.now()
return fn.apply(this, arguments)
}
}
}
Debonce代码实现:
function debounce(fn, wait) {
let timer = null
return function() {
if(timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
fn.apply(this, arguments)
}, wait)
}
}
使用高阶函数的好处:
- 封装基础组件
- 代码复用,代码模块化
- 保持业务逻辑模块代码的纯净
- 符合软件工程的高内聚低耦合
编程范式
- 命令式
- 声明式
命令式
const arr = [1, 2, 3]
let arr2 = []
for (let i = 0; i < arr.length; i++) {
arr2.push(arr[i] * 3)
}
声明式
let arr = [1, 2, 3]
const three = x => x * 3
arr.map(three)