0

My code was compiled to the following, and it works, but I do not know why. The variable that references the incrementing value is not included as an argument in the for loop.

var _loop2 = function _loop2() {
    var p = document.createElement('p');
    p.setAttribute('class', 'location__result');
    p.setAttribute('data-id', response.features[i].id);
    p.setAttribute('data-center', response.features[i].center);
    p.textContent = response.features[i].place_name;
    p.addEventListener('click', function () {
        endingInput.value = p.textContent;
        endingResults.style.display = "none";
        placeIconAndZoom(p, position);
    });
    endingResults.appendChild(p);
};

for (var i = 0, length = response.features.length; i < length; i++) {
    _loop2();
}
  • 4
    Possible duplicate of: [JavaScript loop variable scope](https://stackoverflow.com/questions/18465211/javascript-loop-variable-scope) – Tyler Roper Dec 13 '19 at 19:24
  • @Ruzihm I don't think this is a closure. I think @TylerRoper is right. The `i`declaration is hoisted to the top of scope. – Codebling Dec 13 '19 at 19:26
  • 1
    It is a closure, what else would it be? – ASDFGerte Dec 13 '19 at 19:26
  • @CodeBling I was mostly referring to the "simplest example of a closure" example [here](https://stackoverflow.com/a/111200/1092820) – Ruzihm Dec 13 '19 at 19:27
  • Possible duplicate of: [How do JavaScript closures work?](https://stackoverflow.com/q/111102/1092820) (see "simplest example of a closure" [here](https://stackoverflow.com/a/111200/1092820) ) – Ruzihm Dec 13 '19 at 19:28
  • Agree that it's a dup, but not a closure! @Ruzihm notice in the example you gave that the function was **defined** in the enclosing scope. My understanding is that's a criteria for closure. – Codebling Dec 13 '19 at 19:34
  • @CodeBling `var a = 10; function test() { console.log(a); // will output 10 console.log(b); // will output 6 } var b = 6; test();` ? – Ruzihm Dec 13 '19 at 19:35
  • An easy way to see, that this is a closure, is to create the function in a lower scope: `function f(){ t; }; function g(){ for (var t = 0; t < 1; t++) f(); }; g();`, which will obviously throw, compared to `function g(){ function f(){ t; }; for (var t = 0; t < 1; t++) f(); }; g();`. Alternatively, you can go to the chrome dev tools, and look at the closure directly. – ASDFGerte Dec 13 '19 at 19:35
  • @CodeBling to my knowledge all functions in javascript are closures except those created through `new Function` – Ruzihm Dec 13 '19 at 19:44
  • Ok, maybe I need to be more specific here. Sure, this is a closure in the sense that the function is capturing a variable of the outer ("global") scope. It is **NOT** a closure of the inner loop. You can see this easily by changing the for loop's `var i` to `let i`, at which point _loop2's `i` variable will be `undefined`. In other words, this only works because `var i` is hoisted to the top of the scope, exactly where `var _loop2` is defined. @Ruzihm @ASDFGerte – Codebling Dec 13 '19 at 19:45
  • I agree that this is technically a closure, just not a closure of the inner loop. – Codebling Dec 13 '19 at 19:46
  • that is true, but it's `var i`, not `let i`. – ASDFGerte Dec 13 '19 at 19:47
  • Yes, so maybe my statement about not being a closure was misleading, in which case sorry! I think we're all on the same page. – Codebling Dec 13 '19 at 19:48
  • @CodeBling its a closure of the function that the loop is inside, same as the scope of `i`. Not sure what you're getting at here... – Ruzihm Dec 13 '19 at 19:48
  • @Ruzihm not sure what you mean, but we should probably move this to chat if we're going to continue – Codebling Dec 13 '19 at 19:48
  • 1
    What remains is, that the variable `i` is being found by `_loop2`, because it is in the closure of it. – ASDFGerte Dec 13 '19 at 19:49
  • @ASDFGerte as I've said, we're on the same page. If you feel the need to be told you're correct, you are. – Codebling Dec 13 '19 at 19:54

2 Answers2

0

A function (x) declared inside another function (y) has access to all variables in the scope of the x (unless they are masked by another variable of the same name).

y can also be the global or module scope rather than a function per se.

var i = "example";

function x() {
    console.log(i);
}

x();
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
0

This is the classic case of why const and let were introduced in ES6

var has a function level scope. This differs to const and let in terms of scoping, where the variable defined in var can be accessible anywhere in hits function declaration.

In your case, we declare var i inside the for loop (the function level scope), and your for loop is calling your _loop2 function. Since _loop2 is part of the for loops function scope, you're able to access that variable.

This SO answer can explain it a million times better than I can: What's the difference between using "let" and "var"?

You can fix this by either adding: use 'strict' ontop of your script file, but a much better way is to avoid using var all together (unless there is a special circumstance) and switch it to let

Shiny
  • 4,945
  • 3
  • 17
  • 33
alex067
  • 3,159
  • 1
  • 11
  • 17
  • "var is a global scope" — No, it isn't. It is *function* level scope, not global. `"use strict"` (you misplaced the quotes) has no effect on variables declared with `var`. You are confusing it with global variables that are declared **without** the use of any scope keyword (`var`, `let`, `const`). – Quentin Dec 13 '19 at 19:25
  • Sorry let me edit my answer to be more specific, thanks everyone – alex067 Dec 13 '19 at 19:27
  • Re edit: `"use strict"` which you are still getting the syntax for wrong will still not make a difference here. – Quentin Dec 13 '19 at 19:31