В чем отличие передачи параметров по значению и по ссылке в JavaScript?
Что проверяют
Знаете ли вы, что в JavaScript есть только передача по значению, а «объекты передаются по ссылке» это упрощение, которое ломается на первом же примере. Следом обычно дают код с переприсваиванием параметра и спрашивают, что выведет консоль, а во фронтенде переходят к иммутабельности состояния.
Как отвечать
Точная формулировка: аргумент всегда копируется, но у объекта значением переменной служит ссылка. Функция получает копию этой ссылки, это называют передачей через разделение (call by sharing). Отсюда два разных поведения:
- мутация видна снаружи:
obj.key = 1внутри функции меняет тот же объект, потому что обе копии ссылки указывают на него; - переприсваивание не видно:
obj = { key: 1 }внутри функции меняет только локальную копию. При настоящей передаче по ссылке, какrefв C#, поменялась бы и внешняя переменная.
Примитивов семь: string, number, bigint, boolean, undefined, null, symbol. Они неизменяемы, поэтому для них разницы не видно: изменить примитив на месте нельзя в принципе.
Дальше привяжите к фронтенду. React сравнивает состояние через Object.is: если вы мутировали массив и передали в setState тот же объект, ссылка не изменилась, и перерендера не будет. Поэтому обновляют копией: setItems([...items, item]). С пропсами то же: мутация объекта, пришедшего сверху, меняет данные родителя в обход его состояния. Redux Toolkit разрешает «мутирующий» код в редьюсерах только потому, что внутри работает Immer.
Про копирование: spread и Object.assign поверхностные, structuredClone() делает глубокую копию, а JSON.parse(JSON.stringify(x)) теряет Date, undefined, Map и функции.
Где спотыкаются
Говорят «объекты передаются по ссылке» и не могут объяснить, почему переприсваивание параметра не видно снаружи.
Считают, что const делает объект неизменяемым. Он запрещает только переприсвоить переменную, а Object.freeze к тому же поверхностный.
Копируют состояние через spread и мутируют вложенный объект. Верхний уровень новый, вложенные ссылки общие, и изменение протекает в старое состояние.