【问题标题】:Issues with closures and "this" keyword in JavaScriptJavaScript 中的闭包和“this”关键字的问题
【发布时间】:2016-11-01 13:45:37
【问题描述】:

我正在尝试创建一个简单的 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>

【问题讨论】:

  • 您好,在您获得帮助后,请不要破坏您的帖子。这就像在树下避难后砍倒一棵树。请允许其他未来的用户从知识中获益。回答者会付出很多努力。不要浪费他们宝贵的时间。
  • 对不起,我试图重做代码并进行更改并提出不同的问题,而不是发一个完整的其他帖子。
  • @sota7green 也不要这样做 xD 如果您还有其他问题,再问一个问题,不要编辑当前问题。

标签: javascript callback closures this


【解决方案1】:

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

通常当你这样做时

var equation = new Formula();

equation.updateSign();

this 将是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 来返回一个新的函数,该函数设置了 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')

【讨论】:

  • 非常感谢,我一直在阅读有关 bind/apply 的内容并试图将我的头脑围绕在它周围,但你的解释让它点击了!出于某种原因,当我在浏览器中拉出 HTML 时,实际的方程式并没有为我打印出正确的结果,但它在你的小提琴中有效。你知道这是为什么吗?
  • @sota7green - 我用返回的 ID 修复了一个小错误以使小提琴工作,但忘记在答案中添加它。
  • 有什么方法可以在两个值框都填满后立即执行方程式?例如,我在框中输入 3 和 4 而不更改默认的 '+' 符号并让它立即运行而不更改操作符符号?
  • 当然,您只需从 this.sign 开始作为 + 并检查两个值是否都已给出,如下所示 -> jsfiddle.net/68oj4be8/1
【解决方案2】:

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

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

var equation = new Formula();

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

这个Fiddle 有助于说明。希望对您有所帮助。

【讨论】:

  • 谢谢!这解决了问题。当我出于某种原因输入我的值时,结果不正确。它似乎只打印出第一个数字并根据符号将其设为正数或负数。我的 .calculate 函数有问题吗?
  • 看起来 adeneo 已经发现了这里的错误,他在回答中称这是一个逻辑缺陷。
猜你喜欢
  • 1970-01-01
  • 2018-09-26
  • 1970-01-01
  • 2011-04-22
  • 2011-12-11
  • 2015-07-19
  • 2013-03-20
  • 2011-05-08
  • 1970-01-01
相关资源
最近更新 更多