最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

constants - JavaScript counter increment on each click? - Stack Overflow

programmeradmin3浏览0评论

I need to correct this code in order to make it increment on each click.

<!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>

The solution I have right now works fine, but not sure what are the concepts behind it, the solution is :

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

I need to correct this code in order to make it increment on each click.

<!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>

The solution I have right now works fine, but not sure what are the concepts behind it, the solution is :

inc: function() {
    counter.cnt++;
    console.log(counter.cnt);
}
Share Improve this question edited Dec 11, 2017 at 9:34 ChrisM 1,5866 gold badges22 silver badges29 bronze badges asked Dec 11, 2017 at 9:17 Naveen DINUSHKANaveen DINUSHKA 1,6273 gold badges23 silver badges45 bronze badges 6
  • simply that cnt++ is not incrementing the same cnt inside counter, you need to increment that by doing counter.cnt. – gurvinder372 Commented Dec 11, 2017 at 9:19
  • The concepts you are missing are basically concerned with scope: Which part of your code can see which variables. – Sirko Commented Dec 11, 2017 at 9:19
  • So your code is working with counter.cnt because there is no global variable cnt only counter has it. Is there any other issues? – Justinas Commented Dec 11, 2017 at 9:19
  • You need counter.inc.bind(counter) – Alnitak Commented Dec 11, 2017 at 9:19
  • @Alnitak the bind(counter) what does this do? I actually have not written anything like that but it still works fine – Naveen DINUSHKA Commented Dec 11, 2017 at 9:29
 |  Show 1 more ment

5 Answers 5

Reset to default 8

Its just a scoping issue,

 //Right approach would be,

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

Your erroring code will look for a variable cnt declared in the current scope and traverse until the global one. It will throw error, if it doesn't find a reference.

Since you are passing the inc as an event listener, you have to bind the scope for it, otherwise, the this inside of that function will point to the element which triggers the event. Here in this case, the element would be a button.

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

Or the most readable approach would be,

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

Another reason for avoiding .bind is, once if you bind a context to a function using .bind. You cannot override the context of it after that. Even using .call/.apply

In the button.addEventListener() call you need to use either:

counter.inc.bind(counter)

or (since you appear to be using ES6)

() => counter.inc()

as the registered callback.

You also need to reference the correct cnt (i.e. this.cnt) within the inc method.

The problem with your code is:

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

cnt will refer to a global variable, not the property of counter as you want. You need to set it using this.cnt++.

The second things, is when you bind your addEventListener, it only passes the function, so this context when the function is called, is not actually the counter. You need to change it to:

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

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

or bind the counter.inc to counter like:

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

Use this.cnt to access the cnt variable inside the function.

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

Also you need to bind the value of this to counter inside the function like this:

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

Explaination:

Here we are providing a callback function as the second argument to addEventListener function. For this inside this callback to be equal to the counter object we are using bind.

According to MDN Web Docs

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

Therefore the value of this inside callback is set to counter and we can access its property cnt as this.cnt.

The concept is that you are in is object literal, object literals encapsulate data, enclosing it in a tidy package, global This minimizes the use of global variables which can cause problems when bining code , in the first example you showed us you are retrieving global cnt variable and incrementing it which does'not exists in global scope, it is in counter scope, to retrieve it's properties and methods you need to call object first and then it's property like this object.(method or property)

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

评论列表(0)

  1. 暂无评论