2014-09-19 51 views
0

我正在使用基於Dojo的Esri的Javascript庫3.10。我遇到範圍問題,儘管嘗試了不同的變化,但我仍然有同樣的結果。可能有更好的方法來做到這一點,但我似乎無法弄清楚。Dojo「On」複選框更改內部for循環範圍問題

我想通過一個包含鍵的對象遍歷一組複選框,然後使用dojo/on分配一個事件處理函數來設置基於該鍵的值,但是,On()中的鍵「setting」。 ..)函數對於所有四次迭代都是相同的。

for (var setting in this.appSettings) { 
    console.log(setting); //prints four different things 
    if (this.hasOwnProperty(setting)) { 
     this.checkboxHandles[setting] = 
       On(this[setting], 'change', function (checked) { 
        //this.setValue(setting, checked) 
        console.log(setting) //prints the last 'setting' whenever checkbox is changed 
       }); 
    } 
} 

因此,在On函數內部設置始終是相同的值,即使for循環通過四個唯一鍵循環。首先,爲什麼會發生這種情況,有什麼建議可以解決這個問題?

回答

1

這是JavaScriptessentials之一。閉包始終通過引用引用其外部範圍變量。這意味着事件處理程序引用了setting變量。但是,當for循環繼續時,setting變量正在引用數組中的下一個值。

這個問題的解決方案就是我們所說的IIFE或立即調用的函數表達式。

如果更換事件處理程序返回功能的功能,例如:

On(appSettings[setting], 'change', function (setting) { 
    return function(checked) { 
    //this.setValue(setting, checked) 
    console.log(setting) //prints the last 'setting' whenever checkbox is changed  
    } 
}(setting)); 

所以,這裏所發生的是,setting變量傳遞給函數的包裝,這樣做的好處是他們是通過價值傳遞的,而不是通過引用。

因此,如果您從該函數內部訪問setting變量,它將引用傳遞給該函數的本地作用域變量setting

它是如何怪異看起來,它的工作原理:http://jsfiddle.net/8sxqn53d/ 解釋這種行爲的一個有趣的slidedeck可以發現here

+0

感謝您的出色答案!我以前肯定聽說過並看到過關閉,但從來沒有遇到過實際情況(或者我認爲)。 – roemhildtg 2014-09-19 14:19:45

+0

沒問題,將IIFE放在你的腳本文件中是一種常見的做法。例如,很多jQuery插件都是這樣做的,因爲它們是按值傳遞jQuery對象的,所以以後不能更改它。 – g00glen00b 2014-09-19 15:57:43