如何实现类似winston中format的可调用且可挂载方法的JS对象
实现既支持直接调用、又可挂载方法的函数对象
JavaScript 中函数本身就是引用类型的对象,因此天然支持直接在函数上挂载自定义属性和方法,这就是 winston 中 format 设计的核心逻辑。
实现步骤
- 定义核心基础函数,作为直接调用的入口
- 直接为该函数对象添加属性/方法,作为命名空间下的内置能力
代码实现示例
以下是模拟 winston format 能力的最小实现:
// 1. 定义核心format基础函数,支持直接调用创建自定义格式化器 function format(formatFn, opts = {}) { // 返回格式化器函数 return function formatter(info) { return formatFn(info, opts); }; } // 2. 给format函数挂载内置方法 // 多格式化器组合方法 format.combine = function(...formatters) { return function combinedFormatter(info) { let currentInfo = info; for (const fmt of formatters) { currentInfo = fmt(currentInfo); // 格式化返回false则终止后续处理 if (!currentInfo) return false; } return currentInfo; }; }; // 时间戳内置方法 format.timestamp = function(opts = { format: 'YYYY-MM-DD HH:mm:ss' }) { return function timestampFormatter(info) { // 简化时间生成逻辑,实际生产可引入dayjs等日期库处理 info.timestamp = new Date().toISOString().slice(0, 19).replace('T', ' '); return info; }; }; // 模板格式化内置方法 format.printf = function(templateFn) { return function printfFormatter(info) { info.message = templateFn(info); return info; }; };
使用示例
和你提供的 winston 用法完全一致:
// 直接调用format函数创建自定义请求过滤格式化器 const isRequest = format((info, _opts) => { if (info.isRequest) { return info; } return false; }); // 调用format挂载的内置方法组合格式 const logFormat = format.combine( format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), format.printf((info) => { return `${info.timestamp} ${info.level}: ${info.message}`; }) );
TypeScript 类型适配
如果使用 TypeScript,可以通过接口合并的方式定义类型避免报错:
interface Format { (formatFn: (info: Record<string, any>, opts: Record<string, any>) => Record<string, any> | false, opts?: Record<string, any>): (info: Record<string, any>) => Record<string, any> | false combine: (...formatters: Array<(info: Record<string, any>) => Record<string, any> | false>) => (info: Record<string, any>) => Record<string, any> | false timestamp: (opts?: { format?: string }) => (info: Record<string, any>) => Record<string, any> printf: (templateFn: (info: Record<string, any>) => string) => (info: Record<string, any>) => Record<string, any> } const format = function(formatFn, opts = {}) { // 核心逻辑同上 } as Format; // 后续挂载方法时会自动做类型校验 format.combine = function(/* 实现逻辑 */) {}
内容的提问来源于stack exchange,提问作者HenriDev
相关产品推荐
相关产品推荐

