You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现类似winston中format的可调用且可挂载方法的JS对象

实现既支持直接调用、又可挂载方法的函数对象

JavaScript 中函数本身就是引用类型的对象,因此天然支持直接在函数上挂载自定义属性和方法,这就是 winston 中 format 设计的核心逻辑。

实现步骤

  1. 定义核心基础函数,作为直接调用的入口
  2. 直接为该函数对象添加属性/方法,作为命名空间下的内置能力

代码实现示例

以下是模拟 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 15:15:03