Uncaught TypeError: функция не является функцией - PullRequest
0 голосов
/ 15 января 2019

Я получаю Fib.inputValidate is not a function

Я хочу запустить метод inputValidate, чтобы на keyup вход подтверждался как integer и как Fibonacci число:

HTML выглядит так:

<form id="fibonacci-form" action="" method="post">
  <input id="fibonacci" type="text" name="fibonacci"/>
</form>

Javascript ES6:

class Fibonacci {

  constructor() {
    const isPerfectSquare = '';
    const isFibonacci = '';
    const isInt = '';
    const inputValidate = '';
    this.isPerfectSquare = isPerfectSquare;
    this.isFibonacci = isFibonacci;
    this.isInt = isInt;
    this.inputValidate = inputValidate;
  } // constructor

  inputValidate(valueParsed, isInt) {
    var field = document.getElementById('fibonacci');
    var valueParsed = parseInt(field.value);
    field.addEventListener("keyup", function(e) {
      if (this.isInt(valueParsed) === false && field.value !== '') { 
        alert('Please enter a valid integer.'); 
      } 

      if(this.isFibonacci(valueParsed)) {
        alert(valueParsed + ' is a Fibonacci Number.');  
      } else {
        alert(valueParsed + ' is not a Fibonacci Number.'); 
      }
    });
  }

  isInt(valueParsed) {
    var field = document.getElementById('fibonacci');
    var valueParsed = parseInt(field.value);
    return !isNaN(valueParsed) && valueParsed == valueParsed.toFixed();
  }

  isPerfectSquare(valueParsed) { 
    var field = document.getElementById('fibonacci');
    var valueParsed = parseInt(field.value);
    var squaredValue = parseInt(Math.sqrt(valueParsed).toFixed(0));
    if (field.value !== '') { 
      return (squaredValue * squaredValue == valueParsed); 
    }
  } 

  isFibonacci(valueParsed) {
    var field = document.getElementById('fibonacci');
    var valueParsed = parseInt(field.value);
    var squaredValue = parseInt(Math.sqrt(valueParsed).toFixed(0)); 
      return this.isPerfectSquare(5 * valueParsed * valueParsed + 4) || this.isPerfectSquare(5 * valueParsed * valueParsed - 4); 
  } 
} // class

let Fib = new Fibonacci();
console.log(Fib.inputValidate());

Ответы [ 5 ]

0 голосов
/ 15 января 2019

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

Теперь, когда вы пытались решить реальную проблему, у вас возникла другая проблема , которая заключается в том, что вы скрываете методы класса со свойствами, значениями которых являются пустые строки ''.

Чтобы исправить это, просто удалите конструктор все вместе, поскольку он ничего не делает, и исправьте проблему с this внутри прослушивателя событий. Для этого у вас есть много способов:

  1. Используйте переменную вне области прослушивателя событий, которая называется, например, that, присвойте ей this и используйте that вместо this внутри прослушивателя событий.

Вот так:

var that = this;
field.addEventListener("keyup", function(e) {
    // use 'that' instead of 'this'
    if(that.isInt(valueParsed) ...
});
  1. Используйте функцию стрелки, потому что функции стрелки используют окружающее их значение this:

Вот так:

// notice the arrow function passed to addEventListener
field.addEventListener("keyup", e => {
    // you can now use 'this' here with no problems
    if(this.isInt(valueParsed) ...
});
  1. bind ваш обработчик событий для экземпляра вашего класса. bind Функция создаст новую функцию, для которой значение this всегда будет установлено равным тому, что вы установили.

Вот так:

field.addEventListener("keyup", function(e) {
    // you can now use 'this' here with no problems
    if(this.isInt(valueParsed) ...
}.bind(this)); // bind the function to its surronding 'this' value so 'this' inside it will be the same as 'this' outside it

Рабочий код: Использование функции стрелки

class Fibonacci {
  inputValidate(valueParsed, isInt) {
    var field = document.getElementById('fibonacci');
    var valueParsed = parseInt(field.value);
    field.addEventListener("keyup", e => {
      if (this.isInt(valueParsed) === false && field.value !== '') {
        alert('Please enter a valid integer.');
      }

      if (this.isFibonacci(valueParsed)) {
        alert(valueParsed + ' is a Fibonacci Number.');
      } else {
        alert(valueParsed + ' is not a Fibonacci Number.');
      }
    });
  }

  isInt(valueParsed) {
    var field = document.getElementById('fibonacci');
    var valueParsed = parseInt(field.value);
    return !isNaN(valueParsed) && valueParsed == valueParsed.toFixed();
  }

  isPerfectSquare(valueParsed) {
    var field = document.getElementById('fibonacci');
    var valueParsed = parseInt(field.value);
    var squaredValue = parseInt(Math.sqrt(valueParsed).toFixed(0));
    if (field.value !== '') {
      return (squaredValue * squaredValue == valueParsed);
    }
  }

  isFibonacci(valueParsed) {
    var field = document.getElementById('fibonacci');
    var valueParsed = parseInt(field.value);
    var squaredValue = parseInt(Math.sqrt(valueParsed).toFixed(0));
    return this.isPerfectSquare(5 * valueParsed * valueParsed + 4) || this.isPerfectSquare(5 * valueParsed * valueParsed - 4);
  }
} // class

let Fib = new Fibonacci();
<form id="fibonacci-form" action="" method="post">
  <input id="fibonacci" type="text" name="fibonacci" />
</form>

Расширенный рабочий код:

В вашем коде все еще есть некоторые проблемы, связанные с функциональностью, а не с ошибками:

  1. Вы объявляете функции как имеющие аргументы, но не используете их. Например, аргумент valueParsed вообще не используется, хотя он является аргументом во всех функциях, вместо этого вы каждый раз извлекаете его из элемента DOM. Используйте аргумент.
  2. valueParsed (теперь используется в качестве аргумента) будет инициализироваться внутри inputValidate. Его следует извлекать из прослушивателя событий, а не извне (каждый раз, когда происходит событие, мы должны получить новое значение для valueParsed).
  3. Для проверки используйте Number вместо parseInt, если вы хотите исключить числа с плавающей запятой (использование parseInt позволит числам с плавающей запятой проходить проверку, поскольку от них требуется только целочисленный бит). Также, если проверка не удалась, return, чтобы остановить выполнение следующего кода. Это (проверка) все еще не очень хорошо, но я оставлю это вам.
  4. Предложение: Возможно, вы захотите использовать кнопку и прослушивать щелчки по ней вместо прослушивания ввода keydown в поле, которое раздражает. Создайте кнопку, и когда пользователь нажимает кнопку, проверьте, является ли число, введенное в поле, числом Фиббоначи или нет. Для этого вам нужно всего лишь изменить одну или две строки кода.

class Fibonacci {
  inputValidate() {
    var field = document.getElementById('fibonacci');

    field.addEventListener("keyup", e => {
      var valueParsed = Number(field.value);
      if (this.isInt(valueParsed) === false) {
        alert('Please enter a valid integer.');
        return;
      }

      if (this.isFibonacci(valueParsed)) {
        alert(valueParsed + ' is a Fibonacci Number.');
      } else {
        alert(valueParsed + ' is not a Fibonacci Number.');
      }
    });
  }

  isInt(valueParsed) {
    return !isNaN(valueParsed) && valueParsed == valueParsed.toFixed();
  }

  isPerfectSquare(valueParsed) {
    var squaredValue = parseInt(Math.sqrt(valueParsed).toFixed(0));

    return (squaredValue * squaredValue == valueParsed);
  }

  isFibonacci(valueParsed) {
    var squaredValue = parseInt(Math.sqrt(valueParsed).toFixed(0));
    return this.isPerfectSquare(5 * valueParsed * valueParsed + 4) || this.isPerfectSquare(5 * valueParsed * valueParsed - 4);
  }
} // class

let Fib = new Fibonacci();
<form id="fibonacci-form" action="" method="post">
  <input id="fibonacci" type="text" name="fibonacci" />
</form>
0 голосов
/ 15 января 2019

Проблема поднята для строк ниже в вашем коде.

const inputValidate = '';

this.inputValidate = inputValidate;

что это значит, это означает, что константная переменная inputValidate присвоена this.inputValidate , поэтому this.inputValidate не является функцией.

В отличие от функции inputValidate (valueParsed, isInt) добавлен в прототип созданного объекта для класса по своей природе.

Итак, когда вы позвонили ниже линии

let Fib = new Fibonacci(); 
console.log(Fib.inputValidate());

затем найдите Fib.inputValidate сначала в функциях класса / конструктора, если не найден, то найдите Fib.inputValidate в прототипе.

поэтому, когда вы вызываете Fib.inputValidate () , он находит функцию в своей функции-конструкторе, но обнаруживает Fib.inputValidate - это свойство, подобное переменной, но не функции.

Вот почему отображается Uncaught TypeError: Функция не является функцией

Для наглядного понимания вы можете прочитать статью введите описание ссылки здесь

На самом деле в javascript нет класса, но ES6 вводит ключевое слово класса. На самом деле это ключевое слово класса просто синтаксический сахар.

Таким образом, каждый должен помнить фактический сценарий Класса.

Наконец, некоторые изменения вашего кода:

constructor() {
    const isPerfectSquare = '';
    const isFibonacci = '';
    const isInt = '';
    const inputValidate = '';
  } // constructor

Теперь Fib.inputValidate () будет доступен.

И, наконец, нажатие / нажатие клавиши или любое другое событие это всегда указывает на элемент Dom, поэтому если вы используете функцию стрелки для нажатия клавиши / нажатия клавиши или любое другое событие, то будет указывать на объект класса.

0 голосов
/ 15 января 2019

Удалите this.inputValidate и const inputValidate из вашего конструктора. И напиши свой метод так ...

inputValidate = (valueParsed, isInt) => {
 // do stuff here
};
0 голосов
/ 15 января 2019

Задача

Ваш конструктор перезаписывает каждую функцию в вашем классе. Вот что на самом деле происходит с каждым методом (я использую isInt() в качестве примера, но он точно такой же для каждого):

Вы устанавливаете isInt в '' (пустая строка) в конструкторе:

const isInt = '';

Затем вы создаете свойство с именем isInt и задаете для него isInt строку:

this.isInt = isInt;

Итак, isInt заканчивается пустой строкой. Вот уменьшенный пример:

class Fibonacci {

  constructor() {
    const isInt = '';
    this.isInt = isInt;
  } // constructor

  isInt(valueParsed) {
    var field = document.getElementById('fibonacci');
    var valueParsed = parseInt(field.value);
    return !isNaN(valueParsed) && valueParsed == valueParsed.toFixed();
  }
} // class

let Fib = new Fibonacci();
console.log(Fib);

Как видите, свойство isInt равно "" (пустая строка), поэтому вы не можете вызывать его как функцию - это строка.

Решение

Поместите объявления функций в конструкторе:

class Fibonacci {

  constructor() {
    this.inputValidate = function(valueParsed, isInt) {
      var field = document.getElementById('fibonacci');
      var valueParsed = parseInt(field.value);
      field.addEventListener("keyup", function(e) {
        if (this.isInt(valueParsed) === false && field.value !== '') {
          alert('Please enter a valid integer.');
        }

        if (this.isFibonacci(valueParsed)) {
          alert(valueParsed + ' is a Fibonacci Number.');
        } else {
          alert(valueParsed + ' is not a Fibonacci Number.');
        }
      });
    }

    this.isInt = function(valueParsed) {
      var field = document.getElementById('fibonacci');
      var valueParsed = parseInt(field.value);
      return !isNaN(valueParsed) && valueParsed == valueParsed.toFixed();
    }

    this.isPerfectSquare = function(valueParsed) {
      var field = document.getElementById('fibonacci');
      var valueParsed = parseInt(field.value);
      var squaredValue = parseInt(Math.sqrt(valueParsed).toFixed(0));
      if (field.value !== '') {
        return (squaredValue * squaredValue == valueParsed);
      }
    }

    this.isFibonacci = function(valueParsed) {
      var field = document.getElementById('fibonacci');
      var valueParsed = parseInt(field.value);
      var squaredValue = parseInt(Math.sqrt(valueParsed).toFixed(0));
      return this.isPerfectSquare(5 * valueParsed * valueParsed + 4) || this.isPerfectSquare(5 * valueParsed * valueParsed - 4);
    }
  }
} // class

let Fib = new Fibonacci();
console.log(Fib);
0 голосов
/ 15 января 2019

Удалить (или очистить) ваш конструктор. Методы класса наследуются экземплярами класса автоматически, и поскольку ваш конструктор просто переопределяет их свойствами, значения которых являются пустыми строками.

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