开发者问题收集

在方法addEventListener中,如何将参数x传递给实现console.log(x)的匿名函数来返回事件?

2021-02-19
465

我不明白 console.log(x) 在下面的情况下是如何工作的。 我理解 addEventListener("keydown", function) 表示当按下 keydown 时,执行该函数(此处打印到控制台)。

但是,我真的无法理解当我们在方法 addEventListener() 中将参数传递给匿名函数(此处为 x )时,事情是如何工作的,然后实现 console.log(x) 会将 keydown 事件打印到控制台。

document.addEventListener("keydown", function(x) {
console.log(x); // e.g. KeyboardEvent {isTrusted: true, key: "x", code: "KeyX", location: 0, ctrlKey: false, …}
});

与 (一个小提示是,使用 event 我可以直接使用 function() ,它仍然有效)相同:

document.addEventListener("keydown", function() { //here no need to input `event` as parameter
console.log(event); // e.g. KeyboardEvent {isTrusted: true, key: "x", code: "KeyX", location: 0, ctrlKey: false, …}
});

但是

document.addEventListener("keydown", function() { //no parameter
console.log(x); // Uncaught ReferenceError: x is not defined
});
2个回答

触发事件时,调用的函数默认会获取传递给它的 Event 对象作为参数。在第一种情况下,由于函数的唯一参数是 x ,因此它会接收 Event 对象。实际上,这相当于这样写:

document.addEventListener("keydown", function() {
  var x = event;
  console.log(x);
});

在第二种情况下,您直接通过 event 变量访问 Event 对象(即不将其分配给另一个变量)。在第三种情况下,您尝试访问未定义的变量 x ,因此出现错误消息。

Wais Kamal
2021-02-19

让我们用自己的逻辑复制这些场景,以更好地说明发生了什么。我将通过直接调用回调而不是等待事件来简化一些事情。这对您询问的事情没有任何影响。

设置

让我们考虑以下接受并调用回调的简单函数:

function fire(callback) {
  callback(42);
}

如您所见, fire 将参数传递给回调。

事件处理程序也会发生这种情况:当事件触发时,浏览器将调用事件处理程序并将当前事件对象传递给它。

第一种情况

如果函数定义了 参数 ,它可以访问传递的参数。因此,如果我按如下方式调用 fire

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

然后我的回调接收并记录 42 。我可以为参数选择任何名称,它都会起作用。

这与您的第一个示例相同:您正在定义一个参数并决定将其命名为 x 。您可以给它起任何其他名字。

第二种情况

在此示例中,您正在访问变量 event 。由于变量未在函数内部定义并且不是参数,因此将在外部作用域中查找它(这基本上就是闭包的工作方式)。现在,碰巧 event 是一个 全局变量,它引用当前处理的事件

在我们的玩具示例中,它将如何工作?想象一下 fire 首先将值分配给全局变量:

var globalArg;

function fire(callback) {
  globalArg = 42;
  callback(globalArg);
}

您可以看到,该值可用作回调的参数以及全局变量 globalArg 。这就是为什么这两个示例都可以工作(对应于您的第一个和第二个场景):

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

fire(function() {
  console.log(globalArg);
});

第三种情况

与第二种情况类似, x 是一个既未在函数内部定义的变量,也不是参数。因此,在外部环境中查找该变量。但是,该变量也不存在,因此会引发错误。

Felix Kling
2021-02-19