Есть ли способ заставить арифметические операторы использовать геттеры и сеттеры в Javascript ES6? - PullRequest
1 голос
/ 26 сентября 2019

У меня есть элементарная система идентификации, где число переводится в строку и дополняется нулями не менее 3 цифр.Это прекрасно работает, пока я использую только обычное задание.Есть ли способ заставить арифметические операторы работать и с сеттером?

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сеттеры и геттеры имеют.

В качестве примечания, что вообще происходит с назначением сложения?Я ожидал бы, что результат будет 0055, если что-нибудь странное, так как это число, добавляемое в строку.

Ответы [ 2 ]

1 голос
/ 26 сентября 2019

Ваш геттер и сеттер используются .Вот что происходит.

testid += 5;

переводится в

test.id = test.id + 5

Сначала вызывается геттер, который возвращает "005".Затем он объединяет 5, в результате чего "0055".Так что это эквивалентно:

test.id = "0055";

В установщике он проходит этот тест:

if (num < 100)

Это верно, потому что 55 меньше, чем 100. Так оно и есть:

this._id = '0' + num;

Это объединяет 0 с фронтом, поэтому оно присваивает "00055".

Эту проблему можно решить, если сначала получатель преобразует 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;
    }
  }

Но нет способа заставить += преобразовать строку в число перед выполнением приращения.Получатель не знает, как вы собираетесь использовать значение, он не может вернуть что-то другое, когда свойство является частью операции приращения.

1 голос
/ 26 сентября 2019

Ну, теоретически вы можете сделать '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

Документы

При этом практическим способом было бы иметь два свойства (число и отформатированную строку), как предлагаетсявыше.

...