好吧,基本上, 的值onclick
是一个在单击元素时将被调用的函数。当用户单击元素时,您希望发生的任何事情都会进入函数的主体。
您可以创建一个命名函数,然后将其分配给元素的 onclick 属性:
function youClickedMe() {
...
}
a.onclick = youClickedMe
但这会使命名空间混乱,其函数名称从未在其他任何地方引用。在你需要的地方创建一个匿名函数会更干净。通常,这看起来像这样:
a.onclick = function() { ... }
但是,如果我们用您的具体示例进行尝试:
a.onclick = function() {
ytplayer_playitem = something; // ??
ytplayer_playlazy(1000);
}
我们看到它对something
播放的内容进行了硬编码。我假设原始代码是从一个循环中获取的,该循环会生成几个可点击的链接来播放;使用上面的代码,所有这些链接都会播放相同的内容,这可能不是您想要的。
到目前为止,一切都很简单,但下一个飞跃是棘手的地方。解决方案似乎很明显:如果你在一个循环中,为什么不在函数体内使用循环变量呢?
// THIS DOESN'T WORK
a.onclick = function() {
ytplayer_playitem = i;
ytplayer_playlazy(1000);
}
看起来它应该可以工作,但不幸的i
是,函数内部是指调用i
函数时变量的值,而不是创建函数时的值。当用户单击链接时,创建所有链接的循环将完成并具有其最终值 - 可能是列表中的最后一项或大于该项目的索引,具体取决于循环的编写方式. 无论它的价值是多少,您都会再次遇到所有链接都播放相同项目的情况。i
通过使用返回值是另一个函数的函数,您的代码中的解决方案得到了一些元数据。如果将循环控制变量作为参数传递给生成函数,则它创建的新函数可以引用该参数并始终获取最初传入的值,无论外部参数变量的值发生了什么,因为:
function generate_onclick(j) {
// no matter when the returned function is called, its "j" will be
// the value passed into this call of "generate_onclick"
return function() { ytplayer_playitem = j; ytplayer_playlazy(1000); }
}
要使用它,请在循环中调用它,如下所示:
a.onclick = generate_onclick(i);
每个生成的函数都有自己的j
变量,它永远保持它的值,而不是什么时候改变i
。因此,每个链接都发挥了正确的作用;任务完成!
这正是您发布的原始代码正在做的事情,有一个小区别:就像我解释的第一步一样,作者选择使用匿名函数而不是定义一个命名函数。这里的另一个区别是他们也在定义匿名函数后立即调用它。这段代码:
a.onclick = (function (j) { ... })(i)
是这段代码的匿名版本:
function gen(j) { ... }
a.onclick = gen(i)
由于 JavaScript 的分号插入规则,匿名版本周围需要额外的括号;function (y) {...}(blah)
编译为独立函数定义,后跟括号中的独立表达式,而不是函数调用。