Присвоить события внутри цикла
Уважаемые знатоки, прошу помочь. Как присвоить соответствующей кнопке событие, которое выведет значение из соответствующего поля ввода в консоль?
Вот что имею:
for(i=0;i<3;i++){
inp = document.createElement('input')
btn = document.createElement('input')
inp.className='inpt'
btn.className='but'
btn.type='button'
btn.value = 'click'
document.body.appendChild(inp)
document.body.appendChild(btn)
document.getElementsByClassName('but')[i].onclick = function(){
console.log(document.getElementsByClassName('inpt')[i].value)
}
}
|
document.getElementsByClassName('inpt')[i].value
// ->
this.value
|
Koyf,
Выше правильный вариант подсказали, но вообще ваша проблема в том, что при создании всех коллбеков на onclick они замкнуты на одно и то же окружение(в данном случае -- глобальный объект), соответственно i в них всех вычисляется в последнее значение, вернувшееся из цикла. вот наглядный пример:
arrayOfFunctions = []
i = 10
while(i--) arrayOfFunctions.push(function(){console.log(i)})
i = "foo"
arrayOfFunctions.forEach(function(f){f()})
//>>>> foo
//>>>> foo
//>>>> foo
//>>>> foo
//>>>> foo
//>>>> foo
//>>>> foo
//>>>> foo
//>>>> foo
//>>>> foo
Не всегда очевидное для новичков поведение. Просто имейте это в виду. UPD а добится желаемого эффекта довольно легко: просто компилировать ф-ции на лету:
arr = ["a", "b", "c"]
functions = []
i = -1
while(i < 2){ ++i; functions.push(Function("f", "console.log(arr[" + i + "])")) }
i = -1
while(i < 2){ ++i; functions.push(function(f){console.log(arr[i])}) }
functions.forEach(function(f){f()})
//>>>> a
//>>>> b
//>>>> c
//>>>> c
//>>>> c
//>>>> c
можно еще создавать дополнительные замыкания на каждой итерации или в ES6 можете еще воспользоваться декларацией переменных с блочной видимостью, но злоупотреблять этим не следует, так как это серьезный жер памяти. |
Всем спасибо за помощь, наконец таки разобрался)
Вдруг кому пригодится
for(i=0;i<3;i++){
inp = document.createElement('input')
btn = document.createElement('input')
inp.className='inpt'
btn.className='but'
btn.type='button'
btn.value = 'click'
document.body.appendChild(inp)
document.body.appendChild(btn)
document.getElementsByClassName('but')[i].onclick = Function('f'+i,'console.log(document.getElementsByClassName("inpt")['+i+'].value)')
}
|
Koyf, нет не в этом.
Создание функций из текста - ужасное решение. |
Aetae,
Что в нем плохого? Я, кстати, не спорю, что для данного кейза Ваше решение лучше, о чем упомянул, но в общем случае, им не обойдешься. А из всех вариантов, которые тут возможны, которые сводятся, по сути, к 3-м случаям: создание отдельной структуры указателей(слишком сложно для этого), создание отдельных окружений для каждого коллбека, явно или или подковерно(с блочным сахаром типа let), что ведет к оверхеду по памяти и тормозам при массовом применении и компиляция на ходу, последнее явно предпочтительней |
| Часовой пояс GMT +3, время: 19:06. |