2009-11-22 6 views
4

При нажатии на каждый div он должен предупредить «1», если нажата кнопка «1» или «5», если был нажат div 2. Я попытался сделать этот код настолько простым, насколько это возможно, потому что это необходимо в гораздо большем приложении.Область видимости Javascript в анонимной функции addEventListener

<html> 
<head> 
<style type="text/css"> 
#div1 { background-color: #00ff00; margin: 10px; padding: 10px; } 
#div2 { background-color: #0000ff; margin: 10px; padding: 10px; } 
</style> 
<script type="text/javascript"> 

function init() 
{ 
    var total = 1; 

    var div1 = document.getElementById('div1'), 
     div2 = document.getElementById('div2'); 

    var helper = function(event, id) 
    { 
     if (event.stopPropagation) event.stopPropagation(); 
     if (event.preventDefault) event.preventDefault(); 

     alert('id='+id); 
    } 

    div1.addEventListener('click', function(event) { helper(event, total); }, false); 

    total += 4; 

    div2.addEventListener('click', function(event) { helper(event, total); }, false); 

} 

</script> 
</head> 

<body onload="init();"> 

<div id="div1">1</div> 
<div id="div2">2</div> 

</body> 
</html> 

Благодарим за помощь! :-)

ответ

8

Проблема заключается в том, что слушатели событий и «всего» оба существуют в той же области (INIT())

Функции событий всегда будут ссылаться на общей в пределах объема инициализации(), даже если он изменяется после того, как функции события объявлены

Чтобы обойти это, функции события должны иметь «общее» в своей области, которая не изменится. Можно добавить еще один слой рамки, используя анонимную функцию

Например:

(function (total) { 
    div1.addEventListener('click', function(event) { helper(event, total); }, false); 
}(total)); 

total += 4; 

(function (total) { 
    div2.addEventListener('click', function(event) { helper(event, total); }, false); 
}(total)); 

анонимные функции передаются Init() 'ы текущего „“ общее значение в качестве параметра. Это устанавливает еще одну «общую» область видимости анонимной функции, поэтому не имеет значения, являются ли общие изменения init() или нет, потому что функция события будет FIRST ссылаться на область анонимной функции.

Edit:

Кроме того, вам нужно поместить точку с запятой после закрывающей скобки функции помощника, в противном случае скрипт будет жаловаться, что «событие» не определено.

var helper = function(event, id) 
{ 
    if (event.stopPropagation) event.stopPropagation(); 
    if (event.preventDefault) event.preventDefault(); 

    alert('id='+id); 
}; 
+0

Ааа. Таким образом, эффективное значение становится как указатель переменной, как в переменной C++ *? –

+0

Фактически, он копируется в локальную область. Если бы это был указатель, то он изменился как внутри, так и вне области видимости, что вернет вас к исходной проблеме. – Matt

+2

Пример Gary Matt верен, вот вам небольшая терминология. Вы столкнулись с вашей конкретной проблемой из-за чего-то известного как «закрытие» (http://www.jibbering.com/faq/faq_notes/closures.html), что является большой и мощной функцией JavaScript. Мэтт показал вам, как обойти свойство закрытия (которое иногда мешает вам, как вы видели), используя анонимные функции и метод, известный как currying. См. Http://ejohn.org/blog/partial-functions-in-javascript/ и http://stackoverflow.com/questions/1413916/. –

2

Это почти то же самое, но я думаю, что это будет лучше:

div1.addEventListener('click', function(t){ return function(event) { helper(event, t); }}(total), false); 

вместо:

(function (total) { 
    div2.addEventListener('click', function(event) { helper(event, total); }, false); 
}(total)); 
Смежные вопросы