Почему изменение порядка вызовов функций конструктора приводит к его неисправности? - PullRequest
1 голос
/ 05 марта 2020

Функция ниже создает калькулятор, который сначала поддерживает только сложение и вычитание двух чисел, но может быть расширен с помощью this.addMethod для размещения других операторов, таких как «/», «*» и «** ".

Однако, когда я добавляю новый калькулятор через конструктор (" new ") и добавляю в него новые операции, операция power (" ** ") работает правильно, только если она вызывается первой.

Полный код ниже:

function Calculator() {
  this.supportedOperators = ['+', '-'];

  this.supportedMethods = [
    (a, b) => a + b,
    (a, b) => a - b
  ];

  this.calculate = (str) => {
    for (operator of this.supportedOperators) {
      if (str.includes(operator)) {
        let delimiter = operator.length; // for '**' operator
        let firstOperand = str.slice(0, str.indexOf(operator));
        let secondOperand = str.slice(str.indexOf(operator) + delimiter);

        return this.supportedMethods[this.supportedOperators.findIndex(item => item === operator)]
          (+firstOperand, +secondOperand);
        /* check the supported operators, then use it on operands
                           
                            A mess here, but i tried my best to make it more readable and understandable */

      } else console.log('Unsupported operation');
    }
  };

  this.addMethod = (operator, method) => {
    this.supportedOperators.push(operator);
    this.supportedMethods.push(method);
  }

}

let powerCalc = new Calculator;

powerCalc.addMethod("**", (a, b) => a ** b); // works fine
powerCalc.addMethod("*", (a, b) => a * b);
powerCalc.addMethod("/", (a, b) => a / b);


let result = powerCalc.calculate("4 ** 3"); // 64, as should be(other values also supported)
console.log(result);

Однако, если я изменю порядок в последней последовательности кода, так что добавление операции "**" больше не будет первым, как это:

function Calculator() {
  this.supportedOperators = ['+', '-'];

  this.supportedMethods = [
    (a, b) => a + b,
    (a, b) => a - b
  ];

  this.calculate = (str) => {
    for (operator of this.supportedOperators) {
      if (str.includes(operator)) {
        let delimiter = operator.length; // for '**' operator
        let firstOperand = str.slice(0, str.indexOf(operator));
        let secondOperand = str.slice(str.indexOf(operator) + delimiter);

        return this.supportedMethods[this.supportedOperators.findIndex(item => item === operator)]
          (+firstOperand, +secondOperand);
        /* check the supported operators, then use it on operands
                           
                            A mess here, but i tried my best to make it more readable and understandable */

      } else console.log('Unsupported operation');
    }
  };

  this.addMethod = (operator, method) => {
    this.supportedOperators.push(operator);
    this.supportedMethods.push(method);
  }

}

let powerCalc = new Calculator;

powerCalc.addMethod("*", (a, b) => a * b); // 
powerCalc.addMethod("/", (a, b) => a / b); // those two work fine regardless of order
powerCalc.addMethod("**", (a, b) => a ** b); // changed the order, no works fine

let result = powerCalc.calculate("4 ** 3"); // throws NaN with any value
console.log(result);

Операция питания теперь возвращает NaN.

Я затрудняюсь понять это. Пожалуйста, помогите.

1 Ответ

0 голосов
/ 05 марта 2020

Как отмечалось выше, проблема заключалась в том, что оба оператора ** и * содержат символ "*". Одно из предложенных решений состояло в том, чтобы реализовать sort() так, чтобы операторы с самой длинной длиной были на первом месте.

Другое было использовать другую структуру данных, и я решил пойти с этим. Код приведен ниже:

function Calculator() {

  this.methods = {
    "-": (a, b) => a - b,
    "+": (a, b) => a + b
  };

  this.calculate = function(str) {

    let split = str.split(' '), 
      a = +split[0],
      operator = split[1],
      b = +split[2] // split the input string into an array of two operands converted to numbers and an operator

    if (!this.methods[operator] || isNaN(a) || isNaN(b)) {
      return NaN;
    }

    return this.methods[operator](a, b);
  }

  this.addMethod = function(name, func) {
    this.methods[name] = func;
  };
}

let powerCalc = new Calculator;

powerCalc.addMethod("*", (a, b) => a * b);
powerCalc.addMethod("/", (a, b) => a / b);
powerCalc.addMethod("**", (a, b) => a ** b); // the order doesn't matter anymore

let result = powerCalc.calculate("4 ** 3"); 
alert( result ); // 64, as it should be

Спасибо всем за вклад!

Также в одном из комментариев было указано, что название вопроса не относится к реальной проблеме, с которой я столкнулся. Я отредактирую это в ближайшее время, когда я придумаю лучшую идею. Извините за путаницу, я только начинаю учить JS. Если у вас есть идея, как лучше назвать вопрос, пожалуйста, оставьте его в комментариях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...