2013-01-04 84 views
1

可能重复:
Javascript closure inside loops - simple practical example关闭JavaScript的for循环中不工作

我在与一个PhoneGap的应用程序的盖的问题。我有一个JSON对象,其中包含有关如何创建表单的说明。这大致是这样的代码:

for (var i in this.form.elements) { 
    var element = this.form.elements[i]; 
    switch (element.type) { 
     // other cases 
     case 5: 
      var addThumb, photoInput; 
      addThumb = function (domId) { 
       return function (imgData) { 
        console.log('id: ' + domId); 
        $(domId).attr({src: 'data:image/jpeg;base64,' + imgData}); 
       } 
      }('#thumb-'+element.id); 
      photoInput = $('<input>') 
       .attr({type: 'button', value: element.name, name: element.type, id: element.id, 'class': 'photobutton'}) 
       .click(function (filename, cb) { 
        return function() { 
         console.log('taking photo and saving to ' + filename) 
         takePhoto(filename,addThumb) 
        } 
       }('photo-'+element.id, addThumb) 
      ); 
      photoThumb = $('<img>').attr({id: 'thumb-'+element.id, 'class': 'thumbnail', src: 'img/target.png'}); 
      $('#content').append(photoInput, photoThumb); 
      break; 
    } 
} 

点击photobutton打开一个照相机拍摄照片,它被保存到磁盘。一旦保存,addThumb与base64照片数据一起被调用以替换缩略图图像。每一个为我的测试形式输出是:

taking photo and saving to file photo-686 
id: '#thumb-690 

用于拍摄照片的封闭工作,但当addThumb被称为回调,domId表明,通过对去循环的最后element.id。给定两个缩略图,无论按下哪个按钮,第二个都会被替换。它发生在iPhone和Android上,所以我写它的方式肯定有问题。我做错了什么?

+0

'this.form'是页面上一个真正的'form'元素吗? – Teemu

+0

this.form只是一个对象,没有html元素。它具有html元素的映射关系,以及它们的ID和值应该是什么,比如组合框的值。 – brodney

+0

我猜'form.elements'是数组式的,所以你不应该在这里使用for-in-loop。 – Bergi

回答

2
takePhoto(filename, addThumb) 

这里需要从封闭内传cb变量,而不是addThumb这是不“保护”。似乎你忘了在“保护”它时更改变量名称。

+0

+1我的解释是正确的,但你的捕获OP的意图。它比我的更好,更有用。 –

+0

你是对的!感谢您发现它,您和@dystroy。 – brodney

1

问题是,addThumb变量本身不受闭包保护。它在创建时包含element.i d的值,但在下一次出现的循环中被替换。所以你总是调用最后创建的addThumb函数。

,而不是试图单独保护每个变量,你可以建立一个封闭包围element

for (var i in this.form.elements) { 
    var element = this.form.elements[i]; 
    (function(element){ 
     switch (element.type) { 
     ... 
    })(element); 
}