我想将参数传递给Java事件监听器。
我已经找到了解决方案,但是我无法理解它们为什么起作用或如何起作用以及为什么其他解决方案不起作用。

我有C / C ++背景,但是在Javascript函数中执行的功能大不相同。
您能否帮助我了解以下示例的工作方式以及为什么起作用?

没有参数的代码可以正常工作:

var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction);

function eventFunction()
{
  console.log("works");
}




如果我在eventListener上包括方括号,该函数将执行一次而不会触发事件,然后不执行任何操作:

var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction());

function eventFunction()
{
  console.log("works");
}


我想这是因为该函数是在eventListener上调用的,因此不允许eventListener函数稍后再调用eventFunction。



当我想使用eventFunction传递参数时。
以下内容不起作用:

var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction("works"));

function eventFunction(myStr)
{
    console.log(myStr);
}


它在不触发事件的情况下调用eventFunction,然后在触发事件时不执行任何操作,这与以前的行为相同。
到目前为止,我认为我可以理解。



为了在事件函数中正确传递参数,我找到了以下代码。
以下解决方案可以正常工作:

var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction("works"));

function eventFunction(myStr)
{
  function func(event, myStr)
  {
    console.log(myStr);
  }

  return function(event) {
    func(event,myStr)
  };
}


我注意到的第一件事是未立即调用此eventFunction。
这是为什么?

但是,我不知道如何在每个函数中传递参数。
我知道“ works”字面量会传递给eventFunction上的myStr。
但是,在func函数中,eventFunction没有传递其他事件参数。

另外,为什么eventFunction需要返回一个带有内部调用func函数的参数的另一个函数?

还请注意,我想将参数传递给没有全局作用域的eventFunction,否则将不需要传递参数。

最佳答案

让我们逐步剖析。

一般信息

.addEventListener函数/方法采用2(或3)个参数:


String,其值为事件类型/名称(例如,"click"
指向Function的指针,事件发生时应执行该指针
Boolean,指定是否应使用事件冒泡或事件传播。此参数是可选的,可以省略。


例子1

在第一个示例中,将String"click")和指向FunctioneventFunction)的指针传递到.addEventListener。一切都按预期工作,事件发生并且函数执行。

例子2

在此示例中,将Stringundefined传递给.addEventListener,这不是.addEventListener所期望的。您可能会问自己“我何时传递undefined?”。嗯,这是在您通过在其后添加括号eventFunction来执行()时发生的。在此,JS中的语法与大多数其他语言中的语法相同,在函数的右侧添加括号以执行该函数。

由于您的eventFunction不会显式返回任何内容,因此它会自动返回undefined。因此,这是.addEventListener得到的:

clicker.addEventListener("click", undefined)


但是,由于执行了eventFunction,因此它将"It worked"记录到控制台一次。

例子3

出于与示例2失败相同的原因,此示例失败。

例子4

最后一个示例中的代码有效,因为它使用了称为闭包的概念。实际上有数千个关于此概念的解释,因此我在这里的解释将非常简短。如果您在理解它时遇到困难,请通过google
“ javascript闭包”。

与许多其他语言相比,JavaScript具有函数作用域而不是块作用域。因此,如果您在函数F中定义一个变量并从G内部返回另一个函数F,则G将可以从F内部访问变量和参数。出于演示目的:

function F () {
  var fVariable = 'Defined in F';
  return function G () {
    return fVariable; // <-- this is the closure
  }
}

var funcG = F(); // <-- execute F
funcG(); // -> 'Defined in F';


将这个简短的示例与您的第四个代码进行比较:它们几乎相同。唯一的区别是,您的代码创建了一个额外的函数func

现在,如果您呼叫clicker.addEventListener("click", eventFunction("it works"))
您执行eventFunction,它返回另一个(匿名/ lambda)函数,该函数通过闭包封装"it works"字符串。如果我们手工写出来,这就是.addEventListener所看到的:

clicker.addEventListener("click", function (event) {
  func("it works", event);
});


编辑:解决问题

这是一个工作示例,请注意,我更改了函数名称以反映其用途:

function eventHandlerFactory (myStr) { // <-- eventFunction in your code
  return function executeOnEvent (event) { // <-- executed if an event occurs
    console.log(myStr);
    console.log(event);
  }
}

clicker.addEventListener("click", eventHandlerFactory("it worked"));


eventHandlerFactory函数返回一个函数executeOnEvent,该函数将传递到.addEventListener中。再次手动将其写出,这就是解释器的理解:

clicker.addEventListener("click", function executeOnEvent (event) {
  console.log("it works");
  console.log(event);
});

07-28 11:48