Scopes captured by an EventListener include all let variables but not var variables?

37 Views Asked by At

I have the following code for attaching an event listener to a html element. I understand that the callback for this event listener forms a closure with its lexical environment.

var submit = document.getElementById("submit");
var x = 0;

function attachEventListener(element, x){
    let count = 0;
    let el = document.getElementById("counter");
    element.addEventListener('click', (e) => {
        e.preventDefault();
        count++;
        el.innerHTML = count + ` ${x}`;
    });
}

My question is the difference between the capture of var and let variables through a Script scope. As seen in the two images below, if I define submit and x as var then they do not get captured via a Script scope. But when defined as let variables then they do get captured via a Script scope. My main question is why does the Script Scope get created with the event listener like this?

var elements do not get captured via a script scope. let elements get captured via a script scope.

I tried to declare the variables in the two ways and thought the behaviour for the two would be same in terms of Scope captured by the event listener. I know let variables are block scoped and var are global or local scoped. But did not expect the difference in Script scopes.

1

There are 1 best solutions below

3
Alexander Nenashev On

Top-level var variables are defined as properties of the global object, in a browser that would be window. So no a script scope for them. Though you can isolate var in a module like const/let.

On the other hand const/let top-level variables are defined in script/module scope.

Because of this and other features of var I consider var as legacy, outdated, dangerous and Heisenbuggy. When I come to a team the first thing I prohibit var with ESLint.

var test = 'var';

console.log(window.test);

const test2 = 'const';

console.log(window.test2);
<script type="module">
  
  var moduleVar = 'module var';
  console.log(window.moduleVar);

</script>