Задать вопрос
id_pripyat
@id_pripyat

Выдает ошибку при переборе .children. Что делать?

Есть задание:

/** * Функция должна перебрать все дочерние элементы элемента where * и вернуть массив, состоящий из тех дочерних элементов * следующим соседом которых является элемент с тегом P * Рекурсия - по желанию * * @param {Element} where - где искать * return {Array} * * example * для html '

' * функция должна вернуть: [div, span] * т.к. следующим соседом этих элементов является элемент с тегом P */
Вот мой код:

function findAllPSiblings(where) {
    var children = where.children
    var arr = [];
    for (var i = 0; i < children.length; i++) {
        if (children[i].nextElementSibling.nodeName = 'P') {
            arr.push(children[i])
        }
    }
    return arr;
}


Однако, при вызове функции findAllPSiblings(body) консоль (Firefox) выдает ошибку:

TypeError: children[i].nextElementSibling is null; can't access its "nodeName" property

В Google то же самое. Что делать? Почему не работает?
  • Вопрос задан
  • 187 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 2
0xD34F
@0xD34F Куратор тега JavaScript
У последнего элемента следующего нет, так что в качестве nextElementSibling вы получаете null, а у null нельзя читать свойства. Как победить возникающую ошибку? - проще всего будет вообще не трогать последний элемент, пусть цикл делает на одну итерацию меньше, для этого замените i < children.length на i < children.length - 1. Другой вариант - прежде чем пытаться читать свойства у следующего элемента, проверять, существует ли он, или не является ли текущий последним, или подсовывать вместо отсутствующего элемента пустой объект - актуально в том случае, если перебор элементов организован не через цикл со счётчиком, а с помощью for...of или методов.

Ещё стоит разобраться, чем присваивание отличается от проверки на равенство (nodeName = 'P', ну да, ну да).

Как может выглядеть исправленная (и переписанная) функция:

function findAllPSiblings(el) {
  const result = [];

  for (const n of el.children) {
    if ((n.nextElementSibling || {}).tagName === 'P') {
      result.push(n);
    }
  }

  return result;
}

А вообще, зачем ограничиваться одними лишь p? Давайте решим задачу в чуть более общем виде - пусть функция кроме родительского элемента принимает ещё и селектор, которому должны соответствовать соседи справа:

const getChildrenWithNext = (el, selector) =>
  Array.prototype.filter.call(
    el.children,
    ({ nextElementSibling: n }) => n && n.matches(selector)
  );
Ответ написан
Комментировать
alexey-m-ukolov
@alexey-m-ukolov Куратор тега JavaScript
Почему не работает?
Потому что у последнего элемента по определению не может быть следующего соседа. И если у вас не бесконечная страница, у вас всегда есть последний элемент.

Что делать?
Добавить дополнительную проверку, что следующий элемент существует.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы