← Назад к вопросам
Как работает передача ссылочного типа данных?
2.2 Middle🔥 151 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Примитивы vs Объекты в памяти
В JavaScript есть два типа данных: примитивы (передаются по значению) и объекты (передаются по ссылке).
1. Примитивные типы (By Value)
// Примитивные типы: число, строка, булево, null, undefined, Symbol, BigInt
let a = 5;
let b = a;
a = 10;
console.log(a); // 10
console.log(b); // 5 - не изменилось!
// Почему? Когда b = a, копируется само значение 5
// a и b имеют разные значения в памяти
// В стеке памяти:
// a -> [10]
// b -> [5]
2. Объекты (By Reference)
// Объекты: {}, [], function, Date, RegExp и т.д.
let user1 = { name: 'Alice', age: 30 };
let user2 = user1;
user1.name = 'Bob';
console.log(user1.name); // 'Bob'
console.log(user2.name); // 'Bob' - изменилось!
// Почему? Когда user2 = user1, копируется ССЫЛКА на объект
// Оба user1 и user2 указывают на один и тот же объект в памяти
// В памяти:
// Стек:
// user1 -> [адрес объекта]
// user2 -> [адрес объекта]
// Куча:
// [адрес] -> { name: 'Bob', age: 30 }
3. Проблема: неожиданные изменения
// ПРОБЛЕМА: Изменение через один reference влияет на другой
const person = { name: 'Alice' };
const copyPerson = person;
copyPerson.name = 'Bob';
console.log(person.name); // 'Bob' - пользователь не ожидал!
// Как это путает:
function updateUser(user) {
user.name = 'Charlie';
return user;
}
const original = { name: 'Alice' };
const updated = updateUser(original);
console.log(original.name); // 'Charlie' - оригинал тоже изменился!
console.log(original === updated); // true - один и тот же объект
4. Shallow Copy (поверхностное копирование)
// Shallow copy копирует только верхний уровень
const original = {
name: 'Alice',
address: { city: 'NYC', zip: '10001' }
};
// Способ 1: Spread operator
const copy1 = { ...original };
// Способ 2: Object.assign
const copy2 = Object.assign({}, original);
// Способ 3: Array.from (для массивов)
const arr = [1, 2, 3];
const arrCopy = [...arr];
// ПРОБЛЕМА: Вложенные объекты всё ещё ссылаются на оригинал
copy1.name = 'Bob';
console.log(original.name); // 'Alice' - имя не изменилось
copy1.address.city = 'LA';
console.log(original.address.city); // 'LA' - город изменился!
// Потому что copy1.address и original.address указывают на один объект
5. Deep Copy (глубокое копирование)
// Deep copy копирует всё, включая вложенные объекты
// Способ 1: JSON (работает для простых объектов)
const original = {
name: 'Alice',
address: { city: 'NYC' }
};
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.address.city = 'LA';
console.log(original.address.city); // 'NYC' - не изменилось!
// ПРОБЛЕМА с JSON методом: теряются function, Date, Map, Set
const obj = {
name: 'Alice',
created: new Date(),
greet: () => console.log('Hi')
};
const copy = JSON.parse(JSON.stringify(obj));
console.log(copy.created); // строка, не Date!
console.log(copy.greet); // undefined!
// Способ 2: Рекурсивное копирование
function deepCopy(obj) {
if (obj === null || typeof obj !== 'object') {
return obj; // Примитив или null
}
if (Array.isArray(obj)) {
return obj.map(item => deepCopy(item));
}
const copy = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
const original = {
name: 'Alice',
hobbies: ['reading', 'gaming']
};
const copy = deepCopy(original);
copy.hobbies.push('coding');
console.log(original.hobbies); // ['reading', 'gaming']
console.log(copy.hobbies); // ['reading', 'gaming', 'coding']
// Способ 3: structuredClone (новый стандарт)
const original = { name: 'Alice', created: new Date() };
const copy = structuredClone(original);
console.log(copy.created instanceof Date); // true! (работает!)
6. Передача в функции
// ПРИМИТИВ: передаётся по значению
function modifyNumber(num) {
num = 100;
}
let x = 5;
modifyNumber(x);
console.log(x); // 5 - не изменилось
// ОБЪЕКТ: передаётся по ссылке
function modifyUser(user) {
user.name = 'Bob';
}
const person = { name: 'Alice' };
modifyUser(person);
console.log(person.name); // 'Bob' - изменилось!
// Но если переназначить саму переменную:
function replaceUser(user) {
user = { name: 'Charlie' }; // Переназначение локальной переменной
}
const person = { name: 'Alice' };
replaceUser(person);
console.log(person.name); // 'Alice' - не изменилось!
// Потому что user = {...} меняет только локальную ссылку
7. Практический пример: State в React
// ПЛОХО: Прямое изменение state (мутация)
const [user, setUser] = useState({ name: 'Alice', age: 30 });
function updateName(newName) {
user.name = newName; // Мутируем напрямую
setUser(user); // React может не заметить изменение!
}
// React использует === сравнение
// user === user (true), поэтому нет re-render
// ХОРОШО: Создаём новый объект
function updateName(newName) {
const updatedUser = { ...user, name: newName }; // Shallow copy
setUser(updatedUser);
}
// Или:
function updateName(newName) {
setUser(prev => ({ ...prev, name: newName }));
}
// Для массивов:
const [items, setItems] = useState([1, 2, 3]);
// ПЛОХО:
items.push(4);
setItems(items);
// ХОРОШО:
setItems([...items, 4]);
// или
setItems(prev => [...prev, 4]);
8. Проверка типа и копирование
// Проверь тип данных
console.log(typeof 5); // 'number' - примитив
console.log(typeof {}); // 'object' - объект
console.log(typeof []); // 'object' - массив это объект!
console.log(typeof null); // 'object' - null это ошибка в JS!
// Правильная проверка
function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
console.log(isObject({})); // true
console.log(isObject([])); // true
console.log(isObject(5)); // false
console.log(isObject(null)); // false
// Определи нужен ли copy
const primitive = 5;
const primitiveCopy = primitive; // Просто копируется
const obj = { id: 1 };
const objShallowCopy = { ...obj }; // Нужен copy для безопасности
Ответ: примитивы передаются по значению (копируются), объекты передаются по ссылке (указывают на один объект в памяти). Используй shallow copy ({...}) или deep copy (structuredClone) для безопасного копирования.