Установка onclick для использования текущего значения переменной в цикле
Название может не иметь смысла, да и описание само по себе не имеет смысла, поэтому вот пример кода:
for(var a=0;a<10;a++) {
var b=document.createElement('b')
b.onclick=function() {
alert(a)
}
b.innerHTML=a
document.body.appendChild(b)
}
Странно то, что когда я устанавливаю innerHTML в a, он использует текущее значение a. Итак, этот код создает десять <b>
элементы со значениями 0, 1, 2, 3, 4, 5, 6, 7, 8 и 9. Это отлично работает. Что не является, однако, функцией onclick. Возвращает окончательное значение a
(10) при нажатии любого из этих элементов. Я попытался установить другую переменную в a
а затем с помощью этой другой переменной в событии onclick, но все равно он возвращает окончательное значение a
, Как бы я использовал это значение a
когда онклик установлен?
2 ответа
Попробуйте следующее
b.onclick= function(arg) {
return function() {
alert(arg);
}
}(a);
Проблема, с которой вы столкнулись, заключается в том, что javascript не использует область видимости блока. Вместо этого все переменные имеют время жизни своей содержащей функции. Так что был только один a
захвачен во всех onclick
функции, и они все видят это окончательное значение.
Решение обходит это, создавая новую функцию и значение для каждой области, а затем немедленно устанавливая это значение на текущее значение a
,
Вот версия, которая немного расширена и, возможно, немного более читабельна
var createClickHandler = function(arg) {
return function() { alert(arg); };
}
for(var a=0;a<10;a++) {
var b=document.createElement('b')
b.onclick = createClickHandler(a);
b.innerHTML=a
document.body.appendChild(b)
}
Один грязный обходной путь, который я обнаружил, заключается в использовании .value
свойство созданного объекта для хранения аргумента, который мы хотим передать .onclick
функция. Так что я могу сделать что-то вроде
for(var a=0;a<10;a++) {
var b=document.createElement('b')
b.value=a
b.onclick=function() {
myfunc(this.value)
}
b.innerHTML=a
document.body.appendChild(b)
}
function myfunc(n){
console.log(n)
}
Я не уверен, работает ли.value с каждым элементом, но, например, для DIV.
РЕДАКТИРОВАТЬ: Чтобы передать больше значений, чем одно, вы можете объединить их, используя некоторый символ, например _, а затем разделить его
b.value=x+"_"+y+"_"+z
function myfunc(str){
t=str.split("_")
x=t[0]
y=t[1]
z=t[2]
console.log(x+","+y+","+z)
}