2013-07-22 2 views
0

У меня жесткое понимание времени и с помощью замыкания (да, я прочитал How do JavaScript closures work?)Javascript значения закрытия замораживании инкрементора

Моя проблема заключается в следующем:

for (row = 0; row < 10; row++) { 
    for (column = 0; column < 10; column++) { 

     var target = $("#" + Data.Row[row].Column[column].ID); 

     target.mouseenter(function() { 
      var position = CalculatePosition($(this)); 

      alert("row:" + row + ",column:" + column); 

      ... 
     }); 
    } 
} 

Как и следовало ожидать, строка и столбец всегда 9, когда у цели есть указатель мыши над ней. Тогда мой вопрос: как я могу заморозить значение строки и столбца, чтобы анонимная функция mouseevent могла получить свои предполагаемые значения? Я пытался делать что-то вроде

target.mouseenter(function() {}.bind(column)); 

И это, кажется, работает для всего столбца, но тогда, конечно, this больше не обращаясь к цели.

+0

Нах, [ 'bind'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) делает что-то другое, которое вы можете» t здесь (также читайте [о ключевом слове 'this'] (https://developer.mozilla.org/ en-US/docs/Web/JavaScript/Reference/Operators/this)) – Bergi

+0

@Bergi Он может использовать функцию 'bind' like:' function (row, column) {}. bind (target, row, column) '. – Paulpro

+0

Я подозреваю, что вы хотите, чтобы функция узнала, какой элемент был нажат, и каждый элемент имеет другой идентификатор. Правда? –

ответ

5

Самый простой вариант здесь, как правило, определить функцию, которая возвращает обработчик:

function getHandler(row, column) 
    return function() { 
     var position = CalculatePosition($(this)); 
     alert("row:" + row + ",column:" + column); 
     // ... 
    }; 
} 

Затем вызовите эту функцию в цикле, чтобы получить ваш обработчик с соответствующими переменными «фиксированных» их значений во время вызова :

for (row = 0; row < 10; row++) { 
    for (column = 0; column < 10; column++) { 
     var target = $("#" + Data.Row[row].Column[column].ID); 
     target.mouseenter(getHandler(row, column)); 
    } 
} 

Вы также можете сделать это в цикле, в непосредственно исполняющего анонимной функции:

for (row = 0; row < 10; row++) { 
    for (column = 0; column < 10; column++) { 
     var target = $("#" + Data.Row[row].Column[column].ID); 
     target.mouseenter((function(row, column) { 
      return function() { 
       var position = CalculatePosition($(this)); 

       alert("row:" + row + ",column:" + column); 

       ... 
      }; 
     })(row, column))); 
    } 
} 

Но ИМО это намного уродливее и труднее читать.

В любом случае основным подходом здесь является создание новой области функций с использованием переменных цикла в качестве аргументов; теперь, когда вы используете их в обратном вызове обработчика, они больше не ссылаются на переменные внешней области.

+0

В основном пример: http://jsfiddle.net/ZeFxg/ – Ian

+1

+1 Это работает, создавая новое закрытие для каждой итерации через петли, и это замыкание содержит мышь введите обработчик тоже. Таким образом, обработчик для каждого элемента имеет свои собственные значения x и y. –

+0

Спасибо! Теперь решение имеет гораздо больше смысла в моей голове. – Technolar

0

Вы можете использовать bind как так (первый аргумент является контекст (this Arg)):

target.mouseenter(function(row, column){ 
    ... 
}.bind(target[0], row, column)); 

Но привязка не является кросс-браузер, и вы уже используете JQuery, так что вы должны использовать proxy вместо :

target.mouseenter($.proxy(function(row, column){ 
    ... 
}, target[0], row, column)); 
+0

Однако вы должны использовать 'target [0]' для получения только элемента DOM или удалить '$()' из 'this' внутри обработчика. – Bergi

+0

@Bergi Спасибо, я не заметил, что 'target' был объектом jQuery (я предположил, что это« e.target »из какого-либо обработчика событий). Я обновил его, чтобы использовать 'target [0]'. – Paulpro

Смежные вопросы