这个解决方案有效,但我不明白第二个“返回函数()”是做什么的?
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/