EventListener 捕获的范围包括所有 let 变量,但不包括 var 变量?

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

提问人:Ends of Invention 提问时间:10/2/2023 更新时间:10/2/2023 访问量:33

问:

我有以下代码用于将事件侦听器附加到 html 元素。我知道此事件侦听器的回调与其词法环境形成闭包。

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}`;
    });
}

我的问题是通过脚本范围捕获 var 和 let 变量之间的区别。 如下图所示,如果我定义 和 as,则它们不会通过脚本范围捕获。但是,当定义为变量时,它们确实会通过脚本范围捕获。 我的主要问题是为什么像这样使用事件侦听器创建范围?submitxvarletScript

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

我尝试以两种方式声明变量,并认为两者的行为在事件侦听器捕获的范围方面是相同的。我知道 let 变量是块范围的,var 是全局或局部范围的。但没想到脚本范围的差异。

JavaScript 作用域 var let

评论

0赞 Bergi 10/2/2023
你在这里比较苹果和橙子。在第一张图中,你扩展了“Closure (attachEventListener)”范围,在第二张图中,你扩展了“Script”范围。当然,它们是不同的!

答:

0赞 Alexander Nenashev 10/2/2023 #1

顶级变量被定义为全局对象的属性,在浏览器中为 。所以没有他们的脚本范围。虽然您可以在像 .varwindowvarconst/let

另一方面,顶级变量是在脚本/模块作用域中定义的。const/let

由于这个和其他特征,我认为是遗留的、过时的、危险的和Heisenbuggy。当我来到一个团队时,我首先禁止使用ESLint。varvarvar

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>

评论

0赞 Bergi 10/2/2023
您可能需要澄清“脚本范围”的含义。顶级词法声明的范围不限于单个脚本。
0赞 Alexander Nenashev 10/2/2023
@Bergi我同意,只是很难表述,这更像是一个脚本级别,而不是一个脚本范围
1赞 Bergi 10/2/2023
也许可以称之为“全球词汇范围”?