J'obtiens Fib.inputValidate is not a function
Je souhaite exécuter la méthode inputValidate
afin que sur keyup
le l'entrée valide à la fois comme un entier
et comme un Fibonacci
nombre:
HTML ressemble à ceci:
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());
Javascript ES6:
<form id="fibonacci-form" action="" method="post"> <input id="fibonacci" type="text" name="fibonacci"/> </form>
5 Réponses :
Supprimez (ou videz) votre constructeur. Les méthodes de classe sont héritées automatiquement par les instances de la classe, et comme c'est le cas, votre constructeur les remplace simplement par des propriétés dont les valeurs sont des chaînes vides.
Supprimez this.inputValidate
et const inputValidate
de votre constructeur. Et écrivez votre méthode de cette façon ...
inputValidate = (valueParsed, isInt) => { // do stuff here };
Votre constructeur écrase chaque fonction de votre classe. Voici ce qui arrive réellement à chaque méthode (j'utilise isInt ()
comme exemple, mais c'est exactement la même chose pour chacune d'elles):
Vous définissez isInt à
''
(chaîne vide) dans le constructeur:
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);
Ensuite, vous créez une propriété nommée isInt code >, et définissez-le sur
isInt
la chaîne:
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);
Donc isInt
finit par être une chaîne vide. Voici un exemple réduit:
this.isInt = isInt;
Comme vous pouvez le voir, la propriété isInt
est égale à ""
(chaîne vide), c'est pourquoi vous ne pouvez pas l'appeler comme un function - c'est une chaîne.
Placez les déclarations de fonction dans le constructeur:
const isInt = '';
Pourquoi déplaceriez-vous toutes les méthodes dans le constructeur. OP n'a pas besoin de cela, il a juste besoin de résoudre le problème avec la fonction inputValidate
( this
n'étant pas l'instance de la classe), ce qui l'amène à remplacer les méthodes dans le constructeur. Vous n'avez pas résolu cela, donc vous venez d'aggraver le code.
@ibrahimmahrir Désolé, je ne suis pas sûr de suivre. Proposez-vous de supprimer toutes les lignes const
, ou autre chose?
Non. Ce que je dis, c'est que vous avez déplacé les méthodes dans le constructeur, ce qui n'est pas une bonne idée car elles devraient être en dehors de celui-ci comme OP l'a déjà fait. Le problème d'OP est qu'à l'intérieur de inputValidate
, il définit un écouteur d'événements et utilise this
dans ce gestionnaire d'événements. Puisque this
à l'intérieur du gestionnaire d'événements est l'élément et non l'instance, le code ne fonctionne pas. OP a essayé de corriger cela en affectant les méthodes en variables dans le constructeur, cela n'a pas fonctionné, OP a ensuite essayé d'assigner des variables aux méthodes à l'intérieur du constructeur, cela n'a pas fonctionné non plus.
Comment le sais-je? OP a posté une autre question plus tôt qu'il a supprimée.
Ah, je ne le savais pas - j'ai cherché d'autres questions, mais j'ai <10k, donc je n'ai pas pu voir celle-là.
Problème soulevé pour les lignes ci-dessous dans votre code.
const inputValidate = '';
this.inputValidate = inputValidate;
qu'est-ce que cela signifie, cela signifie la variable const inputValidate affectée à this.inputValidate , donc this.inputValidate n'est pas une fonction.
En revanche, la fonction inputValidate (valueParsed, isInt) ajouté dans le prototype de l'objet créé pour la classe par nature.
Ainsi, lorsque vous avez appelé les lignes ci-dessous
constructor() { const isPerfectSquare = ''; const isFibonacci = ''; const isInt = ''; const inputValidate = ''; } // constructor
, recherchez Fib.inputValidate dans les fonctions de classe / constructeur d'abord, si ce n'est pas trouvé, puis recherchez Fib.inputValidate dans le prototype.
donc, quand vous avez appelé Fib.inputValidate () puis il trouve la fonction dans sa fonction constructeur, mais il trouve que Fib.inputValidate est une propriété comme une variable mais pas une fonction.
C'est pourquoi montrer Uncaught TypeError: Function is not a function
Pour une conception claire, vous pouvez lire l'article entrez la description du lien ici
En fait, là Il n'y a pas de classe en javascript mais ES6 introduit un mot-clé de classe, En fait, ce mot-clé de classe est simplement du sucre syntaxique.
Donc, tout le monde devrait garder à l'esprit le scénario réel de la classe.
Enfin quelques modifications de votre code:
let Fib = new Fibonacci(); console.log(Fib.inputValidate());
Maintenant Fib.inputValidate () sera accessible.
Et enfin dans le keypress / keyup ou tout autre événement this pointez toujours l'élément Dom donc si vous utilisez la fonction de flèche pour keypress / keyup ou tout autre événement alors this strong> pointera l'objet de classe.
Le vrai problème est que les gestionnaires d'événements internes this
ne sont pas ce que vous pensez. Le this
à l'intérieur du gestionnaire d'événements sera l'élément (DOM) qui a déclenché l'événement, pas l'instance de votre classe.
Maintenant, pendant que vous essayiez de résoudre le problème réel, vous vous êtes retrouvé avec un autre problème , qui est que vous observez les méthodes de classe avec des propriétés qui ont comme valeurs la chaîne vide ''
.
Pour résoudre ce problème, il suffit de supprimez le constructeur tous ensemble car il ne fait rien, et corrigez le problème avec le this
dans l'écouteur d'événements. Pour ce faire, vous avez de nombreuses façons:
that
, attribuez-lui this
et utilisez that
au lieu de ceci
dans l'écouteur d'événements. Comme ceci:
<form id="fibonacci-form" action="" method="post"> <input id="fibonacci" type="text" name="fibonacci" /> </form>
cette
valeur environnante: Comme ça:
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();
liez
votre gestionnaire d'événements à l'instance de votre classe. lier
une fonction créera une nouvelle fonction dont la valeur this
sera toujours définie sur ce que vous avez défini. Comme ceci:
<form id="fibonacci-form" action="" method="post"> <input id="fibonacci" type="text" name="fibonacci" /> </form>
Code de travail: Utilisation d'une fonction fléchée
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();
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
Code de travail amélioré:
Il y a encore des problèmes avec votre code qui sont liés à la fonctionnalité plutôt qu'à des erreurs:
valueParsed
n'est pas du tout utilisé par même s'il s'agit d'un argument dans toutes les fonctions, mais vous le récupérez à chaque fois depuis l'élément DOM. Utilisez l'argument. valueParsed
(maintenant utilisé comme argument) sera initialisé dans inputValidate
. Il doit être extrait de l'écouteur d'événements et non de l'extérieur (chaque fois que l'événement se déclenche, nous devrions obtenir une nouvelle valeur pour valueParsed
). Number
au lieu de parseInt
si vous souhaitez exclure les nombres flottants (en utilisant parseInt
, les nombres flottants passeront la validation au fur et à mesure seulement le bit entier d'eux). De plus, si la validation échoue, retournez
pour arrêter l'exécution du code supplémentaire. Cela (la validation) n'est toujours pas très bon, je vous laisse cela. keydown
sur le champ, ce qui est ennuyeux. Créez un bouton, et lorsque l'utilisateur clique sur le bouton, vérifiez si le numéro qu'il a entré dans le champ est un Fibbonacci ou non. Vous ne changeriez qu'une ou deux lignes de code pour y parvenir.
// notice the arrow function passed to addEventListener field.addEventListener("keyup", e => { // you can now use 'this' here with no problems if(this.isInt(valueParsed) ... });
var that = this; field.addEventListener("keyup", function(e) { // use 'that' instead of 'this' if(that.isInt(valueParsed) ... });
Supprimez simplement tout
this. [Function] = [function]
du constructeur.Je viens de faire ça, mais ensuite sur
keyup
j'obtiensthis.isInt
n'est pas une fonction.Votre constructeur remplace toutes ses fonctions par une chaîne vide.
@RobMyrick, c'est un problème < / b>