[英]Uncaught TypeError: Function is not a function
我正在获取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());
真正的问题是,内部事件处理程序中的this
不是您认为的那样。 事件处理程序中的this
将是引发事件的(DOM)元素,而不是类的实例。
现在,当您尝试解决实际问题时,最终遇到了另一个问题 ,那就是,您正在使用带有空字符串''
作为值的属性来遮盖类方法。
要解决此问题,只需将构造函数全部删除,因为它不会执行任何操作,并在事件侦听器中解决this
的问题。 为此,您有很多方法:
that
,分配this
给它使用that
不是this
事件监听器里。 像这样:
var that = this;
field.addEventListener("keyup", function(e) {
// use 'that' instead of 'this'
if(that.isInt(valueParsed) ...
});
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) ...
});
bind
事件处理程序bind
到类的实例。 bind
函数将创建一个新函数, this
函数始终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>
增强的工作代码:
您的代码中仍有一些与功能有关的问题,而不是与错误有关的问题:
valueParsed
参数是所有函数中的参数,也根本不会使用它,而是每次都从DOM元素中获取它。 使用参数。 valueParsed
(现在用作参数)将在inputValidate
内部初始化。 应该从事件侦听器内部而不是外部获取(每次事件触发时,我们都应该为valueParsed
获取新值)。 Number
而不是parseInt
(使用parseInt
将使浮点数通过验证,因为它仅从浮点数中获取整数位)。 同样,如果验证失败,请return
以停止执行其他代码。 不过,它(验证)仍然不是很好,我会留给您。 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>
删除(或清空)您的构造函数。 类方法是由类的实例自动继承的,并且因为它是构造函数,因此只需将其值为空字符串的属性覆盖它们即可。
从构造const inputValidate
删除this.inputValidate
和const inputValidate
。 然后这样写你的方法...
inputValidate = (valueParsed, isInt) => {
// do stuff here
};
您的构造函数将覆盖类中的每个函数。 这是每种方法实际发生的情况(我以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);
在您的代码下面的行中提出了问题。
const inputValidate ='';
this.inputValidate = inputValidate;
这是什么意思,它意味着将const变量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:Function不是一个函数
为了使概念清晰,您可以阅读文章, 在此处输入链接描述
javascript中实际上没有类,但是ES6引入了class关键字,实际上,该class关键字只是语法糖。
因此,每个人都应牢记Class的实际情况。
最后,对您的代码进行一些修改:
constructor() {
const isPerfectSquare = '';
const isFibonacci = '';
const isInt = '';
const inputValidate = '';
} // constructor
现在,Fib.inputValidate()将可访问。
最后进入keypress / keyup或任何其他事件, 这总是指向Dom元素,因此,如果将箭头功能用于keypress / keyup或任何其他事件,则这将指向类对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.