为什么在一个循环中动态添加.onclick到一个img元素,需要返回函数()? [英] Why does dynamically adding .onclick to an img element, when in a loop, require return function()?

查看:72
本文介绍了为什么在一个循环中动态添加.onclick到一个img元素,需要返回函数()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  for()这个解决方案有效,但我不明白第二个return function() var i = 0; i< photos.length; i ++){
img.onclick =(function(photo){
return function(){
hotLink(photo); / /window.location ='/ pics / user /'+ photo.user_id;
};
})(photos [i]);

另外,为什么我必须包含(照片[i]);最后?



之前,我有这个,并且onclick会始终链接到最后一张照片[i]。

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


解决方案

有一个照片=照片[我] 那里,你忽略了你的问题):

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

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



实际上点击图像和调用函数,循环已经结束很长时间,并且 photo 从主程序的范围中消失了,但它仍然是在内存中,因为所有这些功能仍然有它的参考。他们会发现它仍然指向列表中的最后一项,因为这是分配给它的最后一件事。



因此,您需要赋予每个onclick函数非常自己的变量一旦创建函数就不会改变。在Javascript中这样做的方式,因为它没有块范围,所以调用一个函数并将该值作为参数传入。函数内部声明的函数参数和变量(与上面非工作示例中的 photo 相反,在函数内 >在其外部声明)是在每个函数调用时创建的。当照片被声明为一个函数参数时,每个onclick都会得到自己的副本,其他任何东西都不能修改,所以当有人最终点击图片时它仍然有正确的值。 / p>

如果它使用静态函数生成器函数,它可能会更清晰一些;真的没有理由做内联的声明和通话的事情。您可以在循环之外声明一次:

 函数makeOnclick(somePhoto){
return function(){hotlink (somePhoto); }
}

然后循环体可以做到这一点:

  img.onclick = makeOnclick(photo)

您打电话给 makeOnclick 并将 photo 作为参数传递。 makeOnclick 函数在很远的地方宣布,即使您想要它也不能直接使用 photo ;它根本看不到那个变量。相反,它所具有的仅仅是它的本地参数 somePhoto - 每次调用 makeOnclick 时都会创建一个全新变量。 。它在调用时初始化为 photo 的值,但它只是一个副本,所以当 photo 更改时在下一次循环迭代中, somePhoto 的特定实例将保持不变。当下一次迭代调用 makeOnclick 时,它将创建一个新实例 somePhoto ,初始化为<$ c的新值$ c>照片,依此类推。因此,即使 makeOnClick 返回的内部函数正在继承 somePhoto var,该var特别为此创建的实例makeOnClick ;每个返回的函数都有它自己的私有 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函数并立即调用它时,它们都很好,并且简洁明了,但不是非常糟糕高效。

This solution works, but I don't understand what the second "return function()" does?

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]);

Also, why do I have to include the (photos[i]); at the end?

Before, I had this, and the onclick would always link to the last photo[i].

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

解决方案

When you do this (assuming there's a photo = photos[i] there that you left out in your question):

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

The variable photo inside the function refers to the same variable as photo outside the function. It's not a snapshot that gets the current value of the variable at the time you define the function; it's just a reference to the same variable. The surrounding loop changes the value of that variable on every iteration, but it doesn't create a new variable each time; it's reusing the same one. So all the functions you generate reference that exact same variable - the one and only photo.

By the time anyone actually clicks on the image and calls the function, the loop has long since terminated, and photo is gone from the main program's scope, but it's still out there in memory because all those functions still have references to it. And they will find it still pointing to the last item in the list, because that was the last thing assigned to it.

So you need to give each onclick function its very own variable that won't change once the function is created. The way to do that in Javascript, since it doesn't have block scope, is to call a function and pass the value in as a parameter. Function parameters and variables declared inside a function (as opposed to photo in the non-working example above, which is used inside the function but declared outside it) are created fresh on every function invocation. When photo is declared as a function parameter, each onclick gets its very own copy that nothing else can modify, so it still has the right value when someone finally clicks the image.

It might be clearer if it used a static function-generator function; there's really no reason to do the inline declare-and-call thing. You could declare this once, outside the loop:

function makeOnclick(somePhoto) {
    return function() { hotlink(somePhoto); }
}

And then the loop body could do this:

img.onclick = makeOnclick(photo)

You're calling makeOnclick and passing it photo as a parameter. The makeOnclick function is declared far away, where it couldn't use photo directly even if you wanted it to; it can't see that variable at all. Instead, all it has is its local parameter somePhoto - which is created as a brand new variable every time you call makeOnclick. It's initialized with the value of photo at the point of the call, but it's just a copy, so when photo changes on the next loop iteration, that particular instance of somePhoto will stay the same. When the next iteration calls makeOnclick, it will create a new instance of somePhoto initialized to the new value of photo, and so on. So even though the inner function that makeOnClick is returning is inheriting the somePhoto var, that var was just created especially for that instance of makeOnClick; every one of those returned functions gets its own private somePhoto.

Your working code above is doing exactly the same thing in a slightly different way. Instead of declaring the makeOnclick function once, outside the loop, and calling it a bunch of times, it's redeclaring it every time through the loop as an anonymous function which it then calls immediately. This code:

img.onclick = (function(x) { blah(x); })(photo);

is the same as this:

function foo(x) { blah(x); }
img.onclick = foo(photo);

without having to give the function a name. In JavaScript in general, this:

(function (x,y,z) { doSomething(x,y,z); })(a,b,c);

is the same as this:

function callDoSomething(x,y,z) { doSomething(x,y,z); }
callDoSomething(a,b,c);

except the function has no name and is not saved anywhere; it goes away right after it's called.

So declaring the onclick-generator function every time through the loop and calling it immediately all at once is nice and concise, but not terribly efficient.

这篇关于为什么在一个循环中动态添加.onclick到一个img元素,需要返回函数()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆