如何通过包装器模块重写moment的now方法并隔离全局影响
解决Moment.js封装时无参数调用不使用自定义now的问题
我明白你的需求:想要封装Moment.js,让调用封装后的momentWrapper()时返回指定的固定时间,同时不影响项目中其他使用原生Moment的代码。目前的问题在于,无参数调用momentWrapper()时,它还是会返回当前真实时间,而不是你设置的固定时间。
问题根源
当你无参数调用moment()时,Moment内部会调用静态方法moment.now()来获取当前时间,而不是原型上的now方法。你的当前实现中,虽然尝试覆盖了now,但:
momentWrapper函数直接转发给moment.apply(this, arguments),无参数时还是会触发原生Moment的逻辑,使用原生的moment.now()- 对静态
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
关键修改点说明
- 无参数调用处理:当没有传入任何参数时,我们主动用
moment(momentWrapper.now())创建对象,强制使用自定义的固定时间,绕过原生Moment的无参数构造逻辑。 - 静态方法覆盖:显式设置
momentWrapper.now = newNow,确保静态方法被正确替换,这样调用momentWrapper.now()也能得到固定时间。 - 保留原型继承:继续沿用原来的原型继承逻辑,保证封装后的对象拥有Moment的所有实例方法。
这样修改后,既实现了你想要的固定时间功能,又不会影响项目中其他使用原生Moment的代码,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Alexander Lallier
相关产品推荐
相关产品推荐

