Представим, что вам дали такой код. Что будет выведено и почему?
let a = 10; let b = a; b = 20; console.log("a:", a); // ? console.log("b:", b); // ? const user = { name: "Alex" }; const user2 = user; user2.name = "Max"; console.log("user:", user); // ? console.log("user2:", user2); // ?
🎯 Зачем спрашивают
📝 Ответ
В JS переменные всегда хранят значения. Для примитивов это сами данные, для объектов — это «ссылка» (указатель) на объект в памяти.
В данном примере мы присваиваем значение переменной
a в переменную b. Так как 10 — числовой тип данных, то значение по факту скопируется.let a = 10; let b = a; b = 20; // a = 10; // b = 20 (сopied);
И связи между переменными нет. А значит, модифицируя переменную
b , мы никак не затронем переменную a.
Совсем другое дело с ссылочным типом данных. Если в переменную присвоено значение ссылочного типа, то в переменной хранится ССЫЛКА на объект в памяти.const user = { name: "Alex" }; const user2 = user;
И данной конструкцией мы НЕ КОПИРУЕМ объект, а создаем еще один “якорь”/ссылку. И оба якоря ведут к одному и тому же объекту.
const user = { name: "Alex" }; const user2 = user; // user2 => user => { name: "Alex" };
Это значит, что мы мутируем не копию, а исходный объект
let a = 10; let b = a; b = 20; console.log("a:", a); // 10 console.log("b:", b); // 20 const user = { name: "Alex" }; const user2 = user; user2.name = "Max"; console.log("user:", user); // { name: "Max" } console.log("user2:", user2); // { name: "Max" }
Не забудьте про функции
В функциях аргументы всегда передаются по значению, то есть копируются. Если в функцию передавать объект, то аргумент содержит именно ссылку на объект. Значит, функция может менять сам объект.
Именно поэтому антипаттерном считается модификация аргументов функции напрямую, потому что это может привести к неочевидным последствиям.
function modifyArray(arr) { // изменяем массив напрямую arr.push(99); console.log("Внутри функции:", arr); } function modifyNumber(x) { // пытаемся изменить число x += 10; console.log("Внутри функции:", x); } const numbers = [1, 2, 3]; console.log("До вызова:", numbers); modifyArray(numbers); // массив изменился снаружи! console.log("После вызова:", numbers); const value = 5; console.log("До вызова:", value); modifyNumber(value); // число осталось тем же console.log("После вызова:", value);
⚖️ Компромиссы
✅ Плюсы | ❌ Минусы |
Понимание механики помогает избегать багов при работе с мутациями. | Но чрезмерное копирование (например, глубокий clone) → дорого по памяти/перформансу. |
ㅤ | Ссылочная семантика может приводить к неожиданным сайд-эффектам (shared state) |
🔎 Встречные вопросы
- Как в JS реализовать иммутабельность?
🚩 Красные флаги
- Исходные переменные не поменяются в обоих случаях
- JS поддерживает передачу по ссылке (неправда).
- Ссылки = указатели (путают с низкоуровневыми языками).
- Упоминание только
code-style, без понимания поведения в памяти.