Вы в основном ответили на свой вопрос. Нарезка за пределами последовательности (по крайней мере для встроенных) не вызывает ошибки. Это имеет смысл, когда вы об этом думаете. Индексирование возвращает один элемент, но нарезка возвращает подпоследовательность элементов. Поэтому, когда вы пытаетесь индексировать несуществующее значение, ничего не вернуть; но когда вы вырезаете последовательность за пределами границ, вы все равно можете вернуть пустую последовательность.
Также обратите внимание, что есть различие между x[3]
и x[3:4]
. Например:
>>> [0, 1, 2, 3, 4, 5][3]
3
>>> [0, 1, 2, 3, 4, 5][3:4]
[3]
Причина, по которой они выглядят одинаково в случае строк, заключается в том, что не существует такой вещи, как отдельный символ за пределами строки; один символ - это всего лишь 1-символьная строка.
forEach
всегда возвращает undefined
, поэтому ваш map
обратный вызов возвращает undefined
, поэтому numbers
будет заполнено undefined
с.
Я думаю, что вы, вероятно, хотите вернуть телефонные номера (каждый number
в массиве phoneNumbers
каждой записи), а затем, возможно, сгладить результат:
const numbers = contacts.map(contact => contact.phoneNumbers.map(({number}) => number)).flat();
Array.prototype.flat
] является относительно новым, но легко заполняется.
Это настолько распространенная модель, что есть метод flatMap
, чтобы сделать это за один раз:
const numbers = contacts.flatMap(contact => contact.phoneNumbers.map(({number}) => number));
Или просто простой цикл с push
:
const numbers = [];
for (const {phoneNumbers} of contacts) {
numbesr.push(...phoneNumbers.map(({number}) => number));
}
Я не знаю, сколько раз я это делал. forEach ничего не возвращает.
const numbers = contacts.reduce((n, c)=>(a.concat(contact.phoneNumbers)),[]);
или
const numbers = contacts.reduce((n, c)=>(a.concat(contact.phoneNumbers.map(pn=>pn.number)),[]);
Вероятно, хотите использовать reduce
и map
let numbers = contacts.reduce((p, c, i) => {
return p.concat(c.phoneNumbers.map(pn => pn.number));
}, []);