Область анонимной функции в качестве аргумента
Я работаю над очень простым приложением. Когда пользователь наводится на любой элемент списка (li
), цвет текста меняется на зеленый, а когда мышь отсутствует, он возвращается в черный цвет.
Почему мы не можем использовать lis[i]
в следующем фрагменте кода внутри анонимной функции вместо ключевого слова this
?
var lis = document.querySelectorAll('li');
var i = 0;
for(; i < lis.length; i++){
lis[i].addEventListener('mouseover', function(){
this.style.color = 'green';
});
lis[i].addEventListener('mouseout', function(){
this.style.color ="black";
});
};
Когда функция обратного вызова будет выполнена, переменная i
будет иметь значение lis.length
из-за цикла, в результате чего значение lis[i]
будет undefined
.
Вместо этого вы можете использовать функцию forEach
.
var lis = document.querySelectorAll('li');
lis.forEach(function (li) {
li.addEventListener('mouseover', function (){
li.style.color = 'green';
});
li.addEventListener('mouseout', function (){
li.style.color ="black";
});
});
<ul>
<li>First LI</li>
<li>Second LI</li>
</ul>
Во время вызова функции цикл будет завершен. Существует только одна переменная i
, и функция всегда видит ее текущее значение. Поэтому, если вы используете i
внутри функции, вы увидите ее со значением lis.length
.
Есть способы обойти это. Если вы можете использовать ES2015 (возможно, через транспилер), вы можете написать:
const lis = document.querySelectorAll('li');
for(let i = 0; i < lis.length; i++){
lis[i].addEventListener('mouseover', () => lis[i].style.color = 'green');
lis[i].addEventListener('mouseout', () => lis[i].style.color ="black");
};
и теперь у вас есть другой i
для каждого цикла цикла.
Или в более старом коде вы можете вывести тело цикла другой функции и передать i
в качестве параметра. Это имеет тот же эффект, что и привязка переменной для каждого события:
var lis = document.querySelectorAll('li');
var _loop = function _loop(i) {
lis[i].addEventListener('mouseover', function () {
return lis[i].style.color = 'green';
});
lis[i].addEventListener('mouseout', function () {
return lis[i].style.color = "black";
});
};
for (var i = 0; i < lis.length; i++) {
_loop(i);
}
(который является кодом, автоматически созданным babel из примера ES2015, который я дал выше)
вы можете использовать "e.srcElement", чтобы получить текущую цель, подобную этой
let lis = document.querySelectorAll('li');
for (let i = 0; i < lis.length; i++) {
lis[i].addEventListener('mouseover', function(e){
e.srcElement.style.color = 'green';
})
lis[i].addEventListener('mouseout', function(e){
e.srcElement.style.color = 'black';
})
}
<ul>
<li>First LI</li>
<li>Second LI</li>
</ul>