2017-05-26 36 views
0

我正在編程創建多個選擇元素,每個選擇元素中有多個選項。我想以編程方式爲每個選擇元素分配它自己的onchange函數,這會告訴我select元素的相應id。只有多個選擇元素的最後附加的onchange函數被稱爲

$(document).ready(function() { 

    // Headers indicate how many select elements I need. 
    // In this example, they are only used to initialize a unique select.id 
    for (var ndx = 0; ndx < headers.length; ndx++) { 
     var header = headers[ndx]; 
     const rowName = header.innerHTML; 
     var select = document.createElement("select"); 
     var options = ["Contains", "Equals", "Starts with", "More than", "Less than", "Between", "Empty", 
      "Doesn't contain", "Doesn't equal", "Doesn't start with", "Is not more than", "Is not between", "Is not empty"]; 

     select.id = rowName + "-select"; 
     options.forEach(function(option) { 
      var element = document.createElement("option"); 
      element.value = option; 
      element.innerHTML = option; 
      select.appendChild(element); 
     }); 
     select.onchange = function() { 
      alert("select.id: " + select.id); 
     } 
    } 
} 

然而,在改變任何選擇元素選項,只有最後一個選擇元素的ID顯示在警報。這可能是一個JavaScript引用問題,我不熟悉?謝謝您的幫助。

+0

難道你不能使用'this'而不是'select'嗎? –

+0

發生這種情況的原因是因爲您在每次迭代中更改了select.id。 'select.id = rowName +「 - 選擇」;「,所以它只輸出最後一個。 JS閉包存儲對超出作用域變量的引用,但它們不存儲像你現在想要的舊值。 –

+1

@AP。哇,你是對的!這對於爲什麼僅顯示最後一個元素的id也是有意義的。謝謝! –

回答

1

JavaScript中的變量被提升到聲明它們的函數作用域的開始處。在實踐中,這意味着每次迭代都會用新的選擇框替換變量select。這意味着所有監聽器都會引用同一個選擇變量,該變量在循環結尾將包含對創建的最後一個選擇的引用。

環繞聽者登記在IIFE(立即調用函數表達),通過它選擇作爲參數。這樣select的值只會被綁定到當前的迭代。

(function(select) { 
    select.onchange = function() { 
     alert(select.id); 
    } 
})(select); 

編輯:

更正確實施監聽器是使用傳遞給它的事件對象的方式:

select.onchange = function(e) { 
    alert(e.target.id); //e.target refers to the element that originated the event 
} 

但我要離開上述答案好,因爲在你的代碼中有一個與提升/範圍相關的問題,這是一個非常常見的錯誤。

相關問題