实现柯里化
原理是利用闭包把传入参数保存起来,当传入参数的数量足够执行函数时,就开始执行函数。
const curry = (fn) =>
(_curry = (...args) =>
// args.length 获取的时调用时传入的参数个数
// fn.length 获取的是定义fn时的形参个数
// 判断实际收集的参数是否达到fn定义时形参的数量,
// 如果达到则运行函数,如果没达到则返回一个函数并继续手机新参数
args.length >= fn.length
? fn(...args)
: (...newArgs) => _curry(...args, ...newArgs));
const sum = (a, b, c, d) => a + b + c + d;
const currySum = curry(sum);
console.log(currySum(1, 2, 3, 4));
console.log(currySum(1, 2)(3, 4));
实现发布订阅 EventEmitter
// subs是EventEmitter私有属性,通过on注册事件,off注销事件,emit触发事件
class EventEmitter {
// ES6实例属性新写法,等价于
constructor() {
this.subs = {};
}
// #subs = {};
// {event:[cbs]}
emit(event, ...args) {
if (this.subs[event] && this.subs[event].length) {
this.subs[event].forEach((cb) => cb(...args));
}
}
on(event, cb) {
(this.subs[event] || (this.subs[event] = [])).push(cb);
}
off(event, offCb) {
if (offCb) {
if (this.subs[event] && this.subs[event].length)
this.subs[event] = this.subs[event].filter((cb) => cb !== offCb);
} else {
this.subs[event] = [];
}
}
}
const event = new EventEmitter();
const cb = function (name) {
console.log(`hello ${name}`);
};
event.on("say", cb);
event.off("say", cb);
event.emit("say", "bar");
实现发布订阅 EventEmitter(2021-07 更新)
// 发布订阅模式
// on emit once off
// 构造函数版本
function EventEmitter(){
this._events={}
}
EventEmitter.prototype.on = function(eventName,callback){
if(!this._events) this._events={};
if(this._events[eventName]){
this._events[eventName].push(callback)
}else{
this._events[eventName] = [callback]
}
}
// 触发订阅的事件
EventEmitter.prototype.emit = function(eventName,...args){
if(!this._events) this._events={};
const callbacks = this._events[eventName];
if(callbacks) callbacks.forEach(callback => callback(...args));
}
// 移除订阅的事件
EventEmitter.prototype.off = function(eventName,callback){
if(!this._events) this._events={};
const callbacks = this._events[eventName];
if(callbacks) this._events[eventName] = callbacks.filter(fn => fn !== callback&&fn.l !==callback)
}
// 订阅一次之后自动取消
EventEmitter.prototype.once = function(eventName,callback){
const one = (...args)=>{
callback(...args);
this.off(eventName,one)
}
// 自定义属性,和原本的callback相关联,用于取消订阅
one.l = callback;
this.on(eventName,one)
}
// class版本
class EventEmitter {
_events={};
on(event,listener){
this._events[event]?this._events[event].push(listener):this._events[event] = [listener];
}
emit(event,...args){
const listeners = this._events[event];
if(listeners) listeners.forEach(callabck => callabck(...args));
}
off(event,listener){
const listeners = this._events[event];
if(listeners) this._events[event] = listeners.filter((callback)=>callback !== listener && callback.l!==listener)
}
once(event,listener){
const once = (...args)=>{
listener(...args);
this.off(event,once)
}
once.l = listener;
this.on(event,once)
}
}
module.exports = EventEmitter;