我想用JavaScript将参数传递给事件侦听器。 我已经找到了解决方案,但我不明白它们为什么或如何起作用,以及为什么其他解决方案不起作用。
我有一个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个)参数:
字符串
,具有事件类型/名称的值(例如“click”
)函数
的指针,该函数应在事件发生时执行布尔值
,指定应使用事件冒泡还是事件传播。 此参数是可选的,可以省略。实施例1
在第一个示例中,您将一个字符串
(“Click”
)和一个指向函数
(EventFunction
)的指针传递给.AddEventListener
。 一切按预期工作,事件发生,函数执行。
实施例2
在本例中,您将字符串
和未定义
传递给.AddEventListener
,这不是.AddEventListener
所期望的。 您可能会问自己“我什么时候传入了undefined
?”。 在执行EventFunction
之后添加了参数()
,就会发生这种情况。 在这里,JS中的语法与大多数其他语言中的语法相等,在函数的右侧添加parens将执行该函数。
因为EventFunction
不显式返回任何内容,所以它自动返回undefined
。 因此,这就是.AddEventListener
得到的:
clicker.addEventListener("click", undefined)
但是,由于您执行了EventFunction
,它将“it Worked”
记录到控制台一次。
实施例3
此示例失败的原因与示例2失败的原因相同。
实施例4
最后一个示例中的代码可以工作,因为它使用了一个称为闭包的概念。 关于这个概念,字面上有上千种解释,所以我在这里的解释会很简短。 如果您无法理解它,只需在谷歌搜索“JavaScript闭包”。
与许多其他语言不同的是,JavaScript具有函数作用域而不是块作用域。 因此,如果您在函数f
中定义一个变量,并从f
中返回另一个函数g
,则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);
});
我注意到的第一件事是这个eventFunction没有立即被调用
它将立即被调用。 但是,它返回一个新函数。 这是为click处理程序注册的函数。 此函数在调用时调用闭包中的函数func
。 传递给这个函数的参数也保留在闭包中。
要理解这个概念,您需要理解闭包是如何工作的。 这是一个已经被广泛讨论过的主题,所以我将只向您指出JavaScript闭包是如何工作的?。