JavaScript 中的闭包和"this"关键字问题



我正在尝试创建一个简单的JavaScript计算器。但是,当我运行代码并对三个字段(值框或符号)中的任何一个进行更改时,我得到一个错误,说明

。计算不是函数

错误出现在this下面。根据是否更改数值或公式符号,计算正在调用的原型函数。

我已经阅读了闭包,回调和"this"关键字,我相信问题在于我如何调用我的原型函数。有人会帮助解释在我的代码我犯了一个错误,以及如何解决它?

这是JavaScript

    var Formula=function() {
    this.value1 = null;
    this.value2 = null;
    this.sign = null;
    this.result = null;
};
Formula.prototype.calculate = function() {
    switch (this.sign) {
    case '+':
        this.result = this.value1 + this.value2;
        break;
    case '-':
        this.result = this.value1 - this.value2;
        break;
    case '/':
        this.result = this.value1 / this.value2;
        break;
    case '*':
        this.result = this.value1 * this.value2;
        break;
    default:
        break;
    } 
    document.querySelector('#result').innerHTML = this.result;
};
Formula.prototype.updateValue = function(event) {
    if (event.currentTarget.id === '#value1')
        this.value1 = parseFloat( event.currentTarget.value );
    else this.value2 = parseFloat( event.currentTarget.value );
    this.calculate();
};
Formula.prototype.updateSign = function(event) {
    this.sign = event.currentTarget.value;
    this.calculate();
};
document.addEventListener('DOMContentLoaded', function () {
(function() {
    var equation = new Formula();
    document.querySelector('#sign').addEventListener('change', equation.updateSign);
    var values = document.querySelectorAll('.value');
    for (var i = 0, numValues = values.length; i < numValues; i++) {
        values[i].addEventListener('change', equation.updateValue);
    }
})();
});
这里是HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="calcJS.js"></script>
</head>
<body>
<input type="number" class="value" id="value1"/>
<select id="sign">
    <option value="+">+</option>
    <option value="-">-</option>
    <option value="*">*</option>
    <option value="/">/</option>
</select>
<input type="number" class="value" id="value2"/> 
= 
<span id="result"/>
</body>
</html>

函数中的this值取决于函数的调用方式。

通常当你做

var equation = new Formula();
equation.updateSign();

this将是updateSign

中的"Formula object"

然而,当你这样做的时候

var equation = new Formula();
document.querySelector('#sign').addEventListener('change', equation.updateSign);

您正在引用函数,而不是调用它,事件处理程序最终调用它,将this值设置为更改的元素,而不是equation对象

如果你想让this成为对象,你必须做像

这样的事情
var equation = new Formula();
document.querySelector('#sign').addEventListener('change', function() {
    equation.updateSign(arguments);
});

或使用bind返回一个具有this集合值的新函数

var equation = new Formula();
document.querySelector('#sign').addEventListener('change', equation.updateSign.bind(equation));

小提琴

你还有一个逻辑缺陷

if (event.currentTarget.id === '#value1')

ID总是不带散列

返回
if (event.currentTarget.id === 'value1')

您看到的问题是由于事件处理的工作方式。当调用事件处理程序时,作为事件目标元素的this隐式传递给处理程序函数。

为了保持原来的this作用域,您需要包装函数并直接调用它。例如:

var equation = new Formula();
document.querySelector('#sign').addEventListener('change', function(event) 
{ 
    equation.updateSign(event); 
});

这提琴有助于说明。

最新更新