javascript - 为什么在循环中动态添加.onclick到img元素需要return function()?

标签 javascript html javascript-events

这个解决方案有效,但我不明白第二个“返回函数()”是做什么的?

for (var i = 0; i < photos.length; i ++) {
    img.onclick = (function(photo) {
        return function() {
            hotLink(photo); //window.location = '/pics/user/' + photo.user_id;  
        };  
    })(photos[i]);

另外,为什么我必须包括 (photos[i]);在最后?

以前,我有这个,onclick 总是链接到最后一张照片[i]。
  for (var i = 0; i < photos.length; i ++) {
      img.onclick = function() {
          window.location = 'pics/user/' + photo.user_id
      };
  }

最佳答案

当你这样做时(假设有一个 photo = photos[i] 你在你的问题中遗漏了):

img.onclick = function() { window.location = 'pics/user/' + photo.user_id };

变量 photo函数内部引用与 photo 相同的变量函数之外。它不是在定义函数时获取变量当前值的快照;它只是对同一变量的引用。周围的循环在每次迭代时都会更改该变量的值,但它不会每次都创建一个新变量;它正在重用同一个。因此,您生成的所有函数都引用了完全相同的变量 - 唯一的 photo .

当任何人真正点击图像并调用函数时,循环早已终止,photo已经从主程序的范围中消失了,但它仍然存在于内存中,因为所有这些函数仍然具有对它的引用。他们会发现它仍然指向列表中的最后一项,因为那是分配给它的最后一项。

因此,您需要为每个 onclick 函数提供其自己的变量,该变量在创建函数后不会更改。在 Javascript 中做到这一点的方法,因为它没有 block 范围,是调用一个函数并将值作为参数传递。在函数内部声明的函数参数和变量(与上面的非工作示例中的 photo 不同,它在函数内部使用但在函数外部声明)在每次函数调用时重新创建。当photo被声明为函数参数,每个 onclick 都有自己的副本,其他任何东西都无法修改,因此当有人最终单击图像时,它仍然具有正确的值。

如果它使用静态函数生成器函数可能会更清楚;真的没有理由做内联声明和调用的事情。您可以在循环外声明一次:
function makeOnclick(somePhoto) {
    return function() { hotlink(somePhoto); }
}

然后循环体可以这样做:
img.onclick = makeOnclick(photo)

您调用makeOnclick并通过它photo作为参数。 makeOnclick函数声明在很远的地方,它不能使用 photo直接,即使你想要它;它根本看不到那个变量。相反,它只有它的本地参数 somePhoto - 每次调用 makeOnclick 时都会创建一个全新的变量.它被初始化为 photo在调用点,但它只是一个副本,所以当 photo在下一次循环迭代中发生变化,somePhoto 的特定实例将保持不变。当下一次迭代调用 makeOnclick ,它将创建 somePhoto 的新实例初始化为 photo 的新值, 等等。所以即使 makeOnClick 的内部函数正在返回正在继承 somePhoto var,该 var 是专门为 makeOnClick 的实例创建的;每个返回的函数都有自己的私有(private) somePhoto .

您上面的工作代码以稍微不同的方式做同样的事情。而不是声明 makeOnclick在循环外运行一次,并多次调用它,每次通过循环将其重新声明为匿名函数,然后立即调用。这段代码:
img.onclick = (function(x) { blah(x); })(photo);

与此相同:
function foo(x) { blah(x); }
img.onclick = foo(photo);

无需给函数命名。在一般的 JavaScript 中,这是:
(function (x,y,z) { doSomething(x,y,z); })(a,b,c);

与此相同:
function callDoSomething(x,y,z) { doSomething(x,y,z); }
callDoSomething(a,b,c);

除了函数没有名称并且没有保存在任何地方;它在被调用后立即消失。

因此,每次通过循环声明 onclick-generator 函数并立即立即调用它既简洁又好,但效率不高。

关于javascript - 为什么在循环中动态添加.onclick到img元素需要return function()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10844048/

相关文章:

html - Internet Explorer 中的表格行高

jquery - 如何在 Twitter Bootstrap 中从一个选项卡链接到另一个选项卡?

javascript - 当使用 PHP include 时切换按钮不起作用

javascript-events - Javascript : "onchange" event does not work with "value" change in "text input" object

javascript - 时间序列数据的线性回归

javascript - chrome 扩展中 background.js 的用途是什么?

javascript - 单击事件不会在移动目标上触发

javascript - 我应该将多个 DOMContentLoaded 处理程序集成到一个中吗?

javascript - 表格 HTML 中的动态数组

javascript - 有什么方法可以防止输入类型 =“number” 获得多个点值吗?