Почему использование $ ('ul li'). Html внутри цикла работает иначе, чем это эквивалентно в vanilla javascript? - PullRequest
0 голосов
/ 27 апреля 2019

Я не понимаю, почему $ ('selector'). Html () работает иначе, чем document.querySelectorAll, когда используется внутри цикла.Я задаю этот вопрос, потому что считаю, что ответ может помочь мне лучше понять замыкания.

Скажем, у меня есть HTML-файл с неупорядоченным списком, содержащим 3 пустых элемента списка.

<ul>
 <li></li>
 <li></li>
 <li></li>
</ul>

ДалееЯ хочу вставить некоторые значения в элементы списка, используя восходящий цикл и jQuery, например так:

$(document).ready(function () {
  for (let i = 0; i < 3; i++) {
    $('ul li').html(i); /// Output: all list items are filled with 2
  }
})

Все элементы списка теперь содержат «2», что не соответствует ожиданиям.Я ожидал 0, 1, 2.

Затем я также попробовал то же самое в JS, и результат был другим

window.onload = function () {
  let list = document.querySelectorAll('ul li');

  for (let i = 0; i < 3; i++){
    list[i].innerHTML = i; //Output: 0 1 2
  }
}

Чтобы найти исправление для версии jQuery на моемкод Я проверил раздел MDN о замыканиях и нашел это исправление:

$(document).ready(function () {
  for (let i = 0; i < 3; i++) {
    $('ul li').html(foo(i)); /// output: 0 1 2
  }

  function foo(n) {
    return function bar(n) {
      return n;
    }
  }
})

Даже если это работает в данный момент, я хотел бы знать, почему использование $ (). html () работает иначе, чемпростой пример JS?

Ответы [ 2 ]

0 голосов
/ 27 апреля 2019

$('ul li').html(i); выбирает все элементы, которые соответствуют селектору (в вашем случае - все li) и устанавливает их html на i. На первой итерации html устанавливается на 0, затем на 1 и, наконец, на 2.

Эквивалент для:

for (let i = 0; i < 3; i++){
    list[i].innerHTML = i; //Output: 0 1 2
}

это

for (let i = 0; i < 3; i++) {
    $('ul li').eq(i).html(i);
}
0 голосов
/ 27 апреля 2019

Проблема в том, что при $('ul li').html( вы всегда выбираете все ul li с и устанавливаете HTML всех из них. На первой итерации вы устанавливаете все ul li с innerHTML на 0. На второй итерации вы устанавливаете все их innerHTML в 1. К концу все их innerHTML равны 2. Вместо этого вам нужно будет перебрать коллекцию $('ul li') :

const lis = $('ul li');
for (let i = 0; i < lis.length; i++) {
  $(lis[i]).html(i); /// output: 0 1 2
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
  <li></li>
  <li></li>
  <li></li>
</ul>

Когда вы вызываете .html с функцией , jQuery вызывает эту функцию с индексом текущего элемента, повторяемого по , и присваивает возвращаемое значение innerHTML этого элемент.

for (let i = 0; i < 3; i++) {
  $('ul li').html(foo(i)); /// output: 0 1 2
}

function foo(n) {
  return function bar(n) {
    return n;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
  <li></li>
  <li></li>
  <li></li>
</ul>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...