-1

I assigned variables in an if-statement that is ALWAYS supposed to run when the code first starts, as seen here:

let started = false;
$(document).on("keypress", function(){
    if (!started){
        let counter = 0;
        started = true;
    }

    console.log(counter++);
});

Yet I get an error that counter, in the console.log(), is undefined. Yet every time the code is executed, 'started' will always be false, meaning 'counter' will always be defined and set to 0. I can't possibly see how console.log() is executed when the definition for 'counter' isn't. I don't see what I'm doing wrong.

rexorsist
  • 97
  • 5
  • 1
    Let ad const are block scoped, if you create it inside the if block, it exists only there – quirimmo Nov 14 '20 at 21:49
  • @quirimmo but the big issue is that counter needs to be a global variable. – Samathingamajig Nov 14 '20 at 21:50
  • 1
    Yeah that actually looks also another issue for keeping the count :D – quirimmo Nov 14 '20 at 21:51
  • Reopened, as it wasn't the best fitting duplicate for the question. But I'd strongly suggest checking other questions - as well as doc - explaining `let` and `const` scopes in details. And yes, `count` should definitely be defined outside that event handler, otherwise its value will be essentially rewritten each time a function is invoked. – raina77ow Nov 14 '20 at 21:53
  • The variable `counter` is defined only within the `if` block. To define a global variable use `var` in place of `let` or define `counter` in the outer block. – user2314737 Nov 14 '20 at 21:56
  • It's not *wrong* to declare it in the `if` block. That depends on your use case. What *is* wrong though in the code you posted is to try to `console.log()` it outside of its scope. – MrUpsidown Nov 14 '20 at 23:03
  • Does this answer your question? [What's the difference between using "let" and "var"?](https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var) – MrUpsidown Nov 14 '20 at 23:09

1 Answers1

2

Variables declared with let and const have block scope. The way scoping works in Javascript is, a variable can be seen only inside the same block that it's declared, or inside child blocks. Since counter is declared inside the if block, it isn't visible outside. In contrast, since started is declared at the top level, everything in the script can see it.

For what you want, declare counter to be a persistent outside variable:

let started = false;
let counter;
$(document).on("keypress", function(){
    if (!started){
        counter = 0;
        started = true;
    }

    console.log(counter++);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

But it would make more sense to use just a counter variable, I think, which gets initialized to 0 immediately:

let counter = 0;
$(document).on("keypress", function(){
    console.log(counter++);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

That's using your original console.log(counter++);, but if you want the value logged to be the current value of counter, use pre-increment instead:

let counter = 0;
$(document).on("keypress", function(){
    console.log(++counter);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

There's also no need for a huge library like jQuery for something this trivial:

let counter = 0;
document.addEventListener('keypress', () => {
    console.log(++counter);
});
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • I think it would also make sense to use `console.log(++counter)` instead so that the logging will always be equal to counter, but that's up to the OP – Samathingamajig Nov 14 '20 at 21:54