回调函数内的词法环境是什么?

What is the lexical environment inside a callback function?

提问人:Abhinav Jha 提问时间:11/17/2021 最后编辑:Sebastian SimonAbhinav Jha 更新时间:11/17/2021 访问量:159

问:

我一直听说箭头函数从它们的词汇环境中继承了 的值。this

请看这个例子:

let para = document.getElementById("para");
let article = document.getElementById("article");

article.addEventListener("click", () => {
  console.log("I’m a <span> tag!", this);
  event.stopImmediatePropagation();
});
para.addEventListener("click", () => console.log("I’m a <p> tag!", this));
<p id="para">
  <span id="article">Click Me!</span>
</p>

为什么 inside 的值是箭头回调函数(或在非严格模式下:)?如果回调函数使用来自其词法环境的值,则词法环境不应该是 ?thisundefinedwindowthisaddEventListener

javascript 回调 这个 arrow-functions 词法范围

评论

1赞 Nicholas Tower 11/17/2021
我只是这样想:无论创建函数时的值是什么,函数运行时的值也会是什么。创建函数时,是窗口。然后将函数传递到 addEventListener 中这一事实不会更改任何内容。thisthis
0赞 Sebastian Simon 11/17/2021
请注意,它确实应该是 ,因为无论如何您都应该在任何地方使用严格模式。在非严格模式下,它也不会是 ,而是 ,这与 相同。undefinedWindowwindowglobalThis
0赞 Abhinav Jha 11/17/2021
非常感谢你们俩,尤其是塞巴斯蒂安。关于评估参数然后调用函数的那句话与我一起点击。
0赞 Abhinav Jha 11/17/2021
你能写下这个评论作为答案吗?

答:

0赞 Benny Yen 11/17/2021 #1

我认为你应该看看MDN上的箭头函数,他们充分解释了箭头函数是什么,并将传统函数与箭头函数进行了比较。

根据 MDN 的说法:

Arrow 函数没有自己的绑定到 this 或 super,不应用作方法。

因此,在您的例子中,箭头函数不会重新定义,即表示是对象thisthiswindow

传统函数是从函数的调用中重新定义的。this

para.addEventListener("click", function () {
    console.log(this);  // print p node elemnt
});
0赞 Sebastian Simon 11/17/2021 #2

当您将函数调用为 时,首先计算,然后计算,然后使用 和 的值调用。 并且不是“内部”.func(a, b)abfuncababfunc

使用以下哪个代码片段并不重要,它们是等效的:

const a = () => console.log(this);

addEventListener("click", a);
addEventListener("click", () => console.log(this));

addEventListener 尝试调用其第二个参数,并将 set 设置为事件的 ,但正如文档和其他各种问答中所解释的那样,箭头函数不能被反弹thiscurrentTarget

"use strict";

(() => console.log(this)).call({ "my": "object" }); // Logs `undefined`.

我不太确定你说的“词汇环境不应该是addEventListener吗? 箭头函数的词法范围是创建它的词法范围。 创建箭头函数时,其作用域和特殊的“lexical-this”标志用于创建函数对象。 在调用时,请注意,尝试执行 OrdinaryCallBindThis 抽象操作(通常设置 )对箭头函数不执行任何操作。 相反,函数体在其原始上下文中按原样执行。this

再看一遍你的原始代码,请注意,每一个都是同一个词法环境的一部分——事实上,无论你把它放在什么地方,在这个代码中都是一样的。 特别要注意的是,函数参数不会创建新的词法环境。thisthis

"use strict";

this; // `undefined`.

let para = document.getElementById("para", this); // Ignored argument, but is `undefined`.
let article = document.getElementById("article");

article.addEventListener("click", () => {
  console.log(this); // Logs `undefined`.
  event.stopImmediatePropagation();
});
para.addEventListener("click", (this, () => console.log(this))); // Logs `undefined`. Preceded by comma operator with discarded value `this`, but would be `undefined`.

相反,一个函数将创建一个新的词法环境,并且还能够被反弹:function

article.addEventListener("click", function(){
  console.log(this); // Logs `article`.
});

有关更详细的说明,请参阅“this”关键字的工作原理。