每次点击都会增加JavaScript计数器?

时间:2017-12-11 09:17:11

标签: javascript const javascript-objects

我需要更正此代码,以便在每次点击时增加。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Clicker</title>
    <meta name="description" content="">
    <style></style>
</head>
<body>
    <button>Click!</button>

<script>
    const counter = {
        cnt: 0,

        inc: function() {
            cnt++;
            console.log(cnt);
        }
    };

    const button = document.getElementsByTagName('button')[0];
    button.addEventListener('click', counter.inc, false);

</script>
</body>
</html>

我现在的解决方案工作正常,但不确定它背后的概念是什么,解决方案是:

inc: function() {
    counter.cnt++;
    console.log(counter.cnt);
}

5 个答案:

答案 0 :(得分:8)

只是一个scoping问题,

 //Right approach would be,

 const counter = {
  cnt: 0,
  inc: function() {
   this.cnt++;
   console.log(this.cnt);
  }
 };

您的错误代码将查找在当前作用域中声明的变量cnt并遍历到全局范围。如果它没有找到参考,它将抛出错误。

由于您将inc作为事件侦听器传递,因此必须为其绑定范围,否则,该函数内部的this将指向触发事件的元素。在这种情况下,元素将是button

button.addEventListener('click', counter.inc.bind(counter), false);

或者最可读的方法是,

button.addEventListener('click', function() { 
 counter.inc() 
}, false);

如果使用.bind将上下文绑定到函数,则避免.bind的另一个原因是。之后你不能覆盖它的上下文。甚至使用.call/.apply

答案 1 :(得分:1)

使用this.cnt访问函数内的cnt变量。

inc: function() {
            this.cnt++;
            console.log(this.cnt);
        }

此外,您需要将this的值绑定到函数内的counter,如下所示:

button.addEventListener('click', counter.inc.bind(counter), false);

<强>阐释:

这里我们提供callback函数作为addEventListener函数的第二个参数。此回调中的this等于我们使用counter的{​​{1}}对象。

根据MDN Web Docs

  

bind()方法创建一个新函数,当被调用时,它具有它   此关键字设置为提供的值,具有给定的序列   调用新函数时提供的任何参数。

因此,回调中bind的值设置为this,我们可以counter访问其属性cnt

答案 2 :(得分:1)

在您需要使用的button.addEventListener()电话中 之一:

counter.inc.bind(counter)

或(因为您似乎使用的是ES6)

() => counter.inc()

作为注册回调。

您还需要在cnt方法中引用正确的this.cnt(即inc)。

答案 3 :(得分:1)

您的代码存在问题:

inc: function() {
   cnt++;
   console.log(cnt);
}

cnt将引用一个全局变量,而不是你想要的计数器的属性。您需要使用this.cnt++设置它。

第二件事是,当你绑定你的addEventListener时,它只传递函数,因此调用函数时this上下文实际上不是计数器。您需要将其更改为:

button.addEventListener('click', function() {
      counter.inc();
}, false);

or button.addEventListener('click', () => counter.inc(), false);

或将counter.inc绑定到计数器上,如:

counter.inc = counter.inc.bind(counter);

答案 4 :(得分:1)

概念是你所处的是对象文字,对象文字封装数据,将其封装在一个整洁的包中,全局这最大限度地减少了在组合代码时可能导致问题的全局变量的使用,在你向我们展示的第一个例子中正在检索全局cnt变量并递增它在全局范围内不存在,它在计数器范围内,检索它的属性和方法,你需要先调用对象然后它的属性就像这个对象。(方法或属性)

inc: function() {
   counter.cnt++;//same as
   this.cnt++;//this
   console.log(counter.cnt);
}