有关闭包的问题以及JavaScript中的“this”关键字

时间:2016-11-01 13:45:38

标签: javascript callback closures this

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

  

this.calculate不是函数

根据您是否更改数值或公式符号,无论调用哪个原型函数,都会在this.calculate下出现错误。

我已经阅读了关闭,回调和“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>

2 个答案:

答案 0 :(得分:1)

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

通常在你做的时候

var equation = new Formula();

equation.updateSign();

this将成为&#34; Formula对象&#34;在updateSign

但是,当你这样做时

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返回具有set this值的新函数

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

FIDDLE

你也有一个逻辑上的缺陷

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

始终返回ID而不使用哈希

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

答案 1 :(得分:0)

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

为了保留原始this范围,您需要包装您的函数并直接调用它。例如:

var equation = new Formula();

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

Fiddle有助于说明。希望有所帮助。