С первой строкой Вы разобрались правильно
Во второй строке используется метод массива reduce, предназначенный для свертки массива
Этот метод принимает 2 аргумента, функцию и инициализирующее значение, притом 2й аргумент не обязателен, если он отсутствует, то в качестве инициализирующего значения будет взят 0й элемент массива, а массив будет обрабатываться начиная с элемента с индексом 1.
Важно! для пустого массива метод reduce просто вернет инициализирующее значение, а если оно опущено - выкинет ошибку. Но здесь это не критично, так как метод строки split никогда не вернет пустой массив, а метод массива map всегда вернет массив той же размерности, что и исходный.
Функция переданная первым аргументом будет вызываться для каждого элемента массива, в нее передается 4 аргумента (в Вашем примере 2 последних опущены за ненадобностью):
- Результат предыдущего вычисления (или инициализирующее значение для первого вызова)
- Текущий элемент массива
- Индекс текущего элемента
- Исходный массив
Функция должна вернуть результат вычисления для текущего элемента, последний результат будет возвращен методом reduce
В третьей строке используется тернарный оператор, формат которого:
<условие> ? <результат при истине условия> : <результат при лжи>
То есть, если sum > 1 - в target запишем 0, иначе 1
Метод массива indexOf производит поиск в массиве по точному совпадению (проверяет оператором ===) с переданным аргументом и возвращает индекс первого найденного элемента или -1 если ничего не нашел
P.S. я бы решил так:
function iqTest(numbers) {
return numbers
.split(' ')
.map((v, i) => ({v: v % 2, i: i + 1}))
.find(({v}, i, arr) => i !== 0 && v !== arr[i - 1].v)
.i;
}