Область анонимной функции в качестве аргумента

86
7

Я работаю над очень простым приложением. Когда пользователь наводится на любой элемент списка (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";
});
};

спросил(а) 2021-01-19T13:31:39+03:00 2 месяца, 3 недели назад
1
Решение
86

Когда функция обратного вызова будет выполнена, переменная 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>

ответил(а) 2021-01-19T13:31:39+03:00 2 месяца, 3 недели назад
75

Во время вызова функции цикл будет завершен. Существует только одна переменная 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, который я дал выше)

ответил(а) 2021-01-19T13:31:39+03:00 2 месяца, 3 недели назад
-4

вы можете использовать "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>

ответил(а) 2021-01-19T13:31:39+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема