Что происходит с индексами элементов при удалении первого элемента из массива
Что проверяют
Понимаете ли вы, что индекс это позиция, а не идентификатор. За вопросом почти всегда стоит продолжение про key в списке и про то, почему после удаления первой строки состояние уезжает к чужому элементу.
Как отвечать
- Массив в JavaScript это объект с числовыми ключами, но методы работают с ним как с плотным списком:
shift()убирает первый элемент, остальные сдвигаются на позицию влево,lengthуменьшается. То же делаетsplice(0, 1), только он возвращает массив удалённого, аshift()само значение. - Стоимость линейная: сдвигаются все элементы. Поэтому удаление из начала в цикле по большому массиву даёт квадратичное время, и для очереди берут либо индекс головы, либо структуру с двумя концами.
delete arr[0]индексы не сдвигает: остаётся дыра,lengthпрежний, массив становится разреженным.mapиforEachпропускают такие позиции, а поведение прочих методов перестаёт совпадать с ожиданиями. В прикладном коде это почти всегда ошибка.- В React состояние не мутируют: новый массив собирают через
filterилиslice, иначе ссылка прежняя и перерисовки не будет. - Главное для фронтенда:
key={index}привязывает элемент к позиции. Удалили первый, ключи съехали, и React решает, что поменялось содержимое каждой строки, а не состав списка. Ключ берут из идентификатора данных.
Где спотыкаются
Отвечают только про сдвиг и не выходят на ключи. Именно там ошибка и болит: после удаления первой строки введённый текст, отмеченная галочка и фокус остаются на своей позиции и оказываются у чужого элемента, хотя сам список выглядит правильно.
Второе: удаляют элементы внутри цикла по возрастающему индексу. После каждого удаления следующий элемент занимает освободившуюся позицию, и цикл его перескакивает. Идут либо с конца, либо собирают новый массив фильтром.
Третье: считают shift() дешёвым, раз это встроенный метод. Сложность у него линейная в любом движке, и на горячем пути с десятками тысяч элементов разница видна в профайлере сразу.