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

Почему не получается отфильтровать массив строк?

Есть код:

let input = document.querySelector('#input');
let tbody = document.querySelector( 'tbody' );
let p = tbody.querySelectorAll( 'p' );
let list = [];
for (const key in p) {
    list.push( p[key].textContent );
}

input.addEventListener('input', function() {
    let matches = list.filter((i)=>i.startsWith(input.value));
   console.log(matches)
   })

В результате которого создается массив строк. Мне нужно его фильтровать, но функция выдаёт ошибку:

TypeError: Cannot read properties of undefined (reading 'startsWith')

Сам массив в порядке, отвечает спокойно на все встроенные функции, за исключением этой.
Отдельно функцию filter также проверяли на других массивах - порядок.
  • Вопрос задан
  • 183 просмотра
Подписаться 1 Простой 2 комментария
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Предлагаю сделать следующее:

  • Прочитать сообщение об ошибке и попытаться осознать, что в нём сказано
  • Посмотреть, какие значения принимает key при переборе p
  • Открыть документацию и разобраться, что делает цикл for...in
  • Погуглить, какие ещё бывают способы перебора

UPD. Ну что, никак?

В сообщении об ошибке сказано, что невозможно прочитать свойство у undefined (ну, так язык устроен). Т.е., массива строк у вас нет. Массив строк - это когда всё его содержимое является строками. Откуда в массиве взялись undefined (да, у вас их там несколько)? Цикл for...in обрабатывает не только собственные свойства объектов, но и те, что доступны через цепочку прототипов. Значения которых уже не являются элементами и, соответственно, не имеют запрашиваемого вами свойства textContent. Раз свойства нет, получаете undefined.

Как собирать массив текстов (const getText = el => el.textContent;), чтобы туда не попадал всякий мусор - лучше бы вообще отказаться от применения for...in, варианты разные есть:

const list = Array.from(p, getText);

// или

const list = Array.prototype.map.call(p, getText);

// или

const list = [];
for (const n of p) {
  list.push(getText(n));
}

// или

const list = [];
for (let i = 0; i < p.length; i++) {
  list[i] = getText(p[i]);
}

// или

const list = [];
p.forEach((n, i) => list.splice(i, 0, getText(n)));

Если же хотите и дальше использовать for...in, то прежде чем что-то делать с конкретным свойством, убедитесь, что оно является собственным, методы Object.hasOwn и Object.prototype.hasOwnProperty вам в этом помогут.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@drawnofmymind
i - не строка? мб i.toString()
Ответ написан
Ваш ответ на вопрос

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

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