在方法链的末尾自动添加方法

Automatically add method at the end of method chain

我正在构建一个 JavaScript class 并且我想 return 在方法链的末尾生成结果而不调用特定方法。

示例 1:myDate('01/01/2000').add(1, 'day') 应该 return 01/02/2000.

示例 2:myDate('01/01/2000').add(1, 'day').format('MMMM D YYYY') 应该 return January 2 2000.

我知道这可以使用 JS class 因为看到它在 DayJs 中工作,我只是不明白如何:https://github.com/iamkun/dayjs/blob/dev/src/index.js#L77

目前,我拥有的是这样的:

class MyDate {
  constructor(date) {
    this.date = date;
  }

  add(count, unit) {
    this.date = // function
    return this; // to enable method chaining
  }

  format() {
    this.date = // function
    return this.date; // to return the desired result
  }

  get() {
    return this.date;
  }
}

// wrapper function to instantiate class on function call
const myDate = date => new MyDate(date);

使用此设置,我得到以下行为:

示例 3:myDate('01/01/2000').add(1, 'day') returns { date: 01/02/2000} 而不是 01/02/2000.

示例 4:myDate('01/01/2000').add(1, 'day').format('MMMM D YYYY') returns January 2 2000 符合预期。

示例 5:myDate('01/01/2000').add(1, 'day').get() returns 01/02/2000 但是我想消除那些唠叨的 get()...

我用谷歌搜索了“js 检测方法链结束”等问题,但找不到任何结果可以解释这是如何工作的。

感谢您的帮助!

从逻辑上讲,class 上的 add 方法应该 return 对象实例而不是特定的成员变量。

你现在拥有的是完美的,这就是任何用户期望它工作的方式。

想象一下您必须添加另一个成员变量的情况,比如说 time 到您的 class 并且您想要链接 object.add(1, 'day').add(5, 'hour') 之类的东西。仅当您的 add 函数 return 是 class.

的一个实例时,您才能实现此目的

最后必须附加一个 get() 方法也很好。考虑著名的 moment.js 包。即使他们有一个 format() 方法来获取实际的日期对象。

希望这能澄清您的困惑。

回过头来看,我想做的是class,具有以下特点:

  • import myDate from "./myDate.js"
  • import { isMyDate } from "./myDate.js"
  • 无需使用new关键字实例化
  • 可以传递无限数量的参数
  • 有函数链接
  • console.log(myDate(params)) 输出自定义字符串 MyDate<date_in_ms)>
  • ${myDate(params)} 输出自定义字符串 date_in_ms

这是一个可能的实现:

// Custom console.log
// Deno: https://doc.deno.land/builtin/stable#Deno.inspect
const inspect = Symbol.for("Deno.customInspect")
// Node: https://nodejs.org/api/util.html#util_util_inspect_custom
// const inspect = Symbol.for('nodejs.util.inspect.custom');

class MyDate {
  constructor(date = new Date(), options) {
    // Set the class's properties
    this._date = date;
    this._options = options;

    // Run initialization tasks
    this.initialize();
  }

  initialize() {
    // if Date, convert time to milliseconds
    if (this._date instanceof Date) {
      this._date = this._date.getTime();
    }
  }

  // Output the result
  format() {
    return this._date;
  }

  // Chainable function
  add(amount) {
    this._date += amount;
    return this;
  }

  // Output all the parameters past after the first one
  options() {
    return this._options;
  }

  // Custom console.log
  [inspect]() {
    return `MyDate<${this._date}>`;
  }

  // Custom String output
  toString() {
    return `${this._date}`;
  }
}

// Automatically instantiate class
const myDate = (date, ...options) => {
  return new MyDate(date, options);
}

// Stand-alone function
const isMyDate = date => date instanceof MyDate;
// Access the stand-alone funtion from the MyDate instance
myDate.isMyDate = date => isMyDate(date);

export default myDate;
export { isMyDate };

Link 至 Dev.to 文章:https://dev.to/rildev/modern-es6-class-48pb

Link 进行概念验证:https://replit.com/@RilDev/ModernES6Class