开发者问题收集

未捕获的类型错误:函数不是函数

2019-01-14
6426

我得到 Fib.inputValidate 不是一个函数

我想要运行 inputValidate 方法,以便在 keyup 上输入既可以验证为 整数 ,也可以验证为 斐波那契 数字:

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());
3个回答

真正的问题 是事件处理程序中的 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 函数将创建一个新函数,该函数的 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>
ibrahim mahrir
2019-01-15

删除(或清空)您的构造函数。类方法会自动被类的实例继承,而您的构造函数只是用值为空字符串的属性覆盖它们。

Hydrothermal
2019-01-14

从构造函数中删除 this.inputValidateconst inputValidate 。然后按如下方式编写方法...

inputValidate = (valueParsed, isInt) => {
 // do stuff here
};
Pablo Darde
2019-01-14