有没有办法让算术运算符在 Javascript ES6 中使用 getter 和 setter?

Is there a way of having arithmetic operators use getters and setters in Javascript ES6?

我有一个基本的 ID 系统,其中一个数字被翻译成一个字符串并用零填充至少 3 位数字。只要我只使用常规作业,它就可以正常工作。有没有办法让算术运算符也与 setter 一起工作?

class Test {
  constructor() {
    this.id = 0;
  }

  /**
   * @param {Number} num
   */
  set id(num) {
    if (num < 10) {
      this._id = '00' + num;
    } else if (num < 100) {
      this._id = '0' + num;
    } else {
      this._id = '' + num;
    }
  }

  get id() {
    return this._id;
  }

  incrementID(increment=1) {
    const id = parseInt(this.id);
    this.id = id + increment;
  }
}

const test = new Test();
test.id = 5;
console.log(`ID is: ${test.id}`); // ID is: 005

test.id += 5;
console.log(`ID is: ${test.id}`); // ID is: 00055 (How?!?)

我知道我可以有一个像我写的那样的 incrementID 方法,但感觉这违背了 ES6 setters 和 getters 的哲学。

作为旁注,加法作业甚至发生了什么?如果有什么奇怪的话,我会期望结果是 0055,因为它是一个被添加到字符串中的数字。

好吧,理论上您可以使 'id' 成为一个对象并提供一个钩子以默认将其转换为数字:

class ID {
    constructor(value) {
        this.value = value;
    }

    [Symbol.toPrimitive](hint) {
        if (hint === 'number' || hint === 'default')
            return Number(this.value)
        return String(this.value);
    }
}

class Test {
    constructor() {
        this.id = new ID('000');
    }

    set id(num) {
        let s;
        if (num < 10) {
            s = '00' + num;
        } else if (num < 100) {
            s = '0' + num;
        } else {
            s = '' + num;
        }
        this._id = new ID(s);

    }

    get id() {
        return this._id;
    }
}


const test = new Test();
test.id = 5;
console.log(`ID is: ${test.id}`); // ID is: 005

test.id += 5;
console.log(`ID is: ${test.id}`); // ID is: 010

Docs

也就是说,一种实用的方法是拥有两个属性(数字和格式化字符串),如上文所建议。

您的 getter 和 setter 正在使用中。这是正在发生的事情。

testid += 5;

翻译成

test.id = test.id + 5

这首先调用了 getter,其中 return 是 "005"。然后它连接 5,导致 "0055"。所以它相当于:

test.id = "0055";

在setter中,它进入了这个测试:

if (num < 100)

这是正确的,因为 55 小于 100。因此:

this._id = '0' + num;

这会将 0 连接到前面,因此它分配了 "00055"

您可以通过让 getter 首先将 num 转换为整数来解决此问题。

  set id(num) {
    num = parseInt(num);
    if (num < 10) {
      this._id = '00' + num;
    } else if (num < 100) {
      this._id = '0' + num;
    } else {
      this._id = '' + num;
    }
  }

但是没有办法让 += 在进行递增之前将字符串转换为数字。 getter 不知道您将如何使用该值,当 属性 是增量操作的一部分时,它不能 return 有什么不同。