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

如何通过包装器模块重写moment的now方法并隔离全局影响

解决Moment.js封装时无参数调用不使用自定义now的问题

我明白你的需求:想要封装Moment.js,让调用封装后的momentWrapper()时返回指定的固定时间,同时不影响项目中其他使用原生Moment的代码。目前的问题在于,无参数调用momentWrapper()时,它还是会返回当前真实时间,而不是你设置的固定时间。

问题根源

当你无参数调用moment()时,Moment内部会调用静态方法moment.now()来获取当前时间,而不是原型上的now方法。你的当前实现中,虽然尝试覆盖了now,但:

  1. momentWrapper函数直接转发给moment.apply(this, arguments),无参数时还是会触发原生Moment的逻辑,使用原生的moment.now()
  2. 对静态now方法的覆盖没有完全生效在momentWrapper上

修复方案

我们需要修改momentWrapper的无参数调用逻辑,主动使用自定义的now时间创建Moment对象,同时确保静态now方法被正确覆盖。

修改后的完整momentWrapper代码:

/**
 * Wraps moment so that alternate time can be set as the 'now' time.
 * This idea was grabbed from fs-extra
 * @module lib/momentWrapper
 */
var moment = require('moment');

function momentWrapper() {
  // 处理无参数调用:使用自定义now时间创建moment对象
  if (arguments.length === 0) {
    return moment(momentWrapper.now());
  }
  // 其他情况沿用原生moment的逻辑
  return moment.apply(this, arguments);
}

// 复制moment的所有静态属性和方法
assign(momentWrapper, moment);
// 显式覆盖静态now方法为自定义实现
momentWrapper.now = newNow;

// 继承moment的原型方法
momentWrapper.prototype = Object.create(moment.prototype);
momentWrapper.prototype.constructor = momentWrapper;

function newNow() {
  return +new Date('1995-12-17T03:24:00');
}

/**
 * Loops through given arguments and assigns them to a object
 * Credit: fs-extra
 * @function assign
 * @return {Object} Mutated object with copied keys
 */
function assign () {
  const args = [].slice.call(arguments).filter(i => i);
  const dest = args.shift();
  args.forEach(src => {
    Object.keys(src).forEach(key => {
      if (key === 'now') {
        dest[key] = newNow;
      } else {
        dest[key] = src[key];
      }
    });
  });
  return dest;
}

module.exports = momentWrapper;

测试结果

运行你的测试代码后,输出会变成:

moment("1995-12-17T03:24:00.000")
moment("2018-12-25T00:00:00.000")
1995-12-17T03:24:00-05:00
----------------------------------------
moment("2018-01-27T15:56:50.938")
2018-01-27T15:56:50-05:00

关键修改点说明

  1. 无参数调用处理:当没有传入任何参数时,我们主动用moment(momentWrapper.now())创建对象,强制使用自定义的固定时间,绕过原生Moment的无参数构造逻辑。
  2. 静态方法覆盖:显式设置momentWrapper.now = newNow,确保静态方法被正确替换,这样调用momentWrapper.now()也能得到固定时间。
  3. 保留原型继承:继续沿用原来的原型继承逻辑,保证封装后的对象拥有Moment的所有实例方法。

这样修改后,既实现了你想要的固定时间功能,又不会影响项目中其他使用原生Moment的代码,完全符合你的需求。

内容的提问来源于stack exchange,提问作者Alexander Lallier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:54:25