2

Следующий код всегда выдает последний результат, то есть 2 (длина массива h):

var h = document.getElementsByClassName('h');
// h.length = 2

for(var i = 0; i < h.length; i++){
    h[i].onclick = function(){
       console.log(i) // выдает последний результат, то есть 2...
    }
}

Как получить i, на котором произошел клик?

Dmitriy Simushev
  • 17,999
  • 5
  • 49
  • 85
cmd
  • 1,530

2 Answers2

3

Это известная особенность JavaScript. Определяя функцию в цикле, вы тем самым создаете замыкание, использующее переменную i. Проблема в том, что используется именно переменная, а не ее текущее значение.

Решение этой проблемы, работающее в ES3+, имеет вид:

var h = document.getElementsByClassName('h');

for(var i = 0; i < h.length; i++){
    h[i].onclick = (function(index) {
        return function(){
            alert(index);
        };
    })(i);
}

JSFiddle: http://jsfiddle.net/b0bn8mfa/

Dmitriy Simushev
  • 17,999
  • 5
  • 49
  • 85
  • Добавлю, что промежуточную функцию лучше вынести из цикла. – Qwertiy Aug 31 '15 at 17:03
1

Подложить что ли свинью?

'use strict';

var h = document.getElementsByClassName('h');

for(let i = 0; i < h.length; i++) { h[i].onclick = function() { console.log(i); } }

<button class=h>1</button>
<button class=h>2</button>
<button class=h>3</button>

А вообще, прочитай про то, как работает замыкание и какая область видимости у переменной: http://learn.javascript.ru/functions-closures

Qwertiy
  • 123,725
  • Стоит упомянуть, что это решение будет работать только в ES6+. – Dmitriy Simushev Aug 31 '15 at 15:48
  • @DmitriySimushev, фраза "Подложить что ли свинью?" как бы намекает, что с этим решением что-то не то :) Там даже use strict неспроста написан. – Qwertiy Aug 31 '15 at 17:02