Javascript,设置 onclick 方法语法

ump*_*mps 2 javascript onclick

我正在查看一个操作 HTML A 标签的 javascript 代码,但我无法理解它如何设置“onclick”属性。它似乎告诉它用索引变量 j 更新 ytplayer_playitem 然后调用 ytplayer_playlazy(1000)

但是所有的括号是怎么回事?javascript 语法中的哪些细节允许像这样设置?

var a = document.createElement("a");
a.href = "#ytplayer";
a.onclick = (function (j) {
    return function () {
        ytplayer_playitem = j;
        ytplayer_playlazy(1000);
    };
})(i);
Run Code Online (Sandbox Code Playgroud)

Mar*_*eed 5

嗯,基本上,值onclick是一个函数,当元素被点击时会被调用。无论您想在用户单击元素时发生什么,都将进入函数体。

您可以创建一个命名函数,然后将其分配给元素的 onclick 属性:

function youClickedMe() {
  ...
}
a.onclick = youClickedMe
Run Code Online (Sandbox Code Playgroud)

但这会使命名空间混乱,其函数名称从未在其他任何地方引用过。在需要的地方创建匿名函数会更简洁。通常,这看起来像这样:

a.onclick = function() { ... }
Run Code Online (Sandbox Code Playgroud)

但是如果我们用你的具体例子来尝试:

a.onclick = function() { 
  ytplayer_playitem = something; // ??
  ytplayer_playlazy(1000); 
}
Run Code Online (Sandbox Code Playgroud)

我们看到它对something播放的内容进行了硬编码。我假设原始代码取自一个循环,该循环会生成几个可点击的链接来播放;使用上面的代码,所有这些链接都会播放相同的内容,这可能不是您想要的。

到目前为止,如此简单,但下一次飞跃变得棘手。解决方案似乎很明显:如果您处于循环中,为什​​么不直接在函数体内使用循环变量呢?

// THIS DOESN'T WORK
a.onclick = function() { 
  ytplayer_playitem = i; 
  ytplayer_playlazy(1000); 
}
Run Code Online (Sandbox Code Playgroud)

看起来它应该可以工作,但不幸的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); }
}
Run Code Online (Sandbox Code Playgroud)

要使用它,请在循环内调用它,如下所示:

a.onclick = generate_onclick(i);
Run Code Online (Sandbox Code Playgroud)

每个生成的函数都有自己的j变量,它永远保持它的值而不是在什么时候改变i。所以每个链接都在发挥正确的作用;任务完成!

这正是您发布的原始代码所做的,只有一个小区别:就像我解释的第一步一样,作者选择使用匿名函数而不是定义命名函数。这里的另一个区别是,他们也在定义匿名函数后立即调用它。这段代码:

a.onclick = (function (j) { ... })(i)
Run Code Online (Sandbox Code Playgroud)

是这段代码的匿名版本:

function gen(j) { ... }
a.onclick = gen(i)
Run Code Online (Sandbox Code Playgroud)

由于 JavaScript 的分号插入规则,匿名版本需要额外的括号;function (y) {...}(blah)编译为独立函数定义,后跟括号中的独立表达式,而不是函数调用。