简体   繁体   中英

Proper incrementing

I am trying to call a function so that when I click on the button it increments until 1,000,000 and then displays it. However when I call it the incrementation only goes to 9627. I can't put my finger on what the problem is.

 <body> <script> var counter = 0; function count() { counter++; document.getElementById('display').value = counter; for (var i = 1; i <= 1000000; i++) count(i); } </script> <div> <center> <button onclick="count();">Let's Count to 1,000,000</button> <input type="number" id="display" value="0"></input> </center> </div> </body>

You're using recursion for the function, and nested scopes are only supported up to a point (that's why you get stuck at ~10k; google "maximum call stack" for further info).

To fix the problem I'd simply throw the recursion away, and just update the counter. The issue with this is that the loop runs pretty fast, and thus the counter will only be updated once it reaches 1M (immediately subsequent changes to an element's value are optimized by the browser, which hangs waiting for the last element.value call before actually re-rendering).

<body>


  <script>
      
    function count() {
          
        var counter = 0; // Putting the counter in here makes the counting repeatable

        for (var i = 1; i <= 1_000_000; i++) {
            counter++;
            document.getElementById('display').value = counter;
        }
    }

  </script>


<div>
    <center>
      <button onclick="count();">Let's Count to 1,000,000</button>
      <input type="number" id="display" value="0"></input>
    </center>

</div>


</body>

Alternatively, if you want the counter to not go as fast as possible (depending on hardware it should never take > 3s to do at max speed), you can use setInterval , or, as referenced by Kinglish in another answer, setTimeout . Here's a snippet with setInterval :

<body>


  <script>

    function count() {

        var counter = 0;

        var incrementer = setInterval(() => {
            // here "incrementer" gets assigned the id of setInterval,
            // that will later be used to clear the interval
            counter++;
            document.getElementById("display").value = counter;
            if (counter >= 1_000_000) {
                clearInterval(incrementer);
            }
        }, 1000 / 30);
        // the second number (30) represents the times the function will
        // be called per second

    }

  </script>


<div>
    <center>
      <button onclick="count();">Let's Count to 1,000,000</button>
      <input type="number" id="display" value="0"></input>
    </center>

</div>


</body>

As mentioned, the way you have this structured is causing a recursion loop which is throwing a Max call stack error. Here's an alternate way, using setTimeout . https://developer.mozilla.org/en-US/docs/Web/API/setTimeout

 let counter = 0, d = document.querySelector('#display'); function count() { d.value = counter; if (++counter < 1000000) setTimeout(() => { count() }, 1); }
 <div> <center> <button onclick="count();">Let's Count to 1,000,000</button> <input type="number" id="display" value="0"></input> </center> </div>

Just use a for loop, it will take a good 5 seconds to reach 1 million but it works:

 <body> <script> var counter = 0; function count() { var counter = 0; for (var i = 1; i <= 1000000; i++) { document.getElementById('display').value = i; } } </script> <div> <center> <button onclick="count();">Let's Count to 1,000,000</button> <input type="number" id="display" value="0"></input> </center> </div> </body>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM