← Назад к вопросам

Что такое передача переменной по значению?

1.0 Junior🔥 191 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Передача переменной по значению

Передача по значению (Pass by Value) — это механизм, при котором функция получает копию значения переменной, а не саму переменную. Изменение параметра внутри функции не влияет на исходную переменную. Это фундаментальное понимание, необходимое для избежания неожиданных ошибок в JavaScript.

Базовое понимание

В JavaScript есть два типа данных:

  • Примитивные типы — передаются по значению
  • Сложные типы (объекты) — передаются по ссылке

Примитивные типы (по значению)

let a = 5;
let b = a; // копируется значение 5

b = 10;

console.log(a); // 5 (не изменилось)
console.log(b); // 10

// Визуально:
// a -> [5] (ячейка памяти 1)
// b -> [10] (ячейка памяти 2, отдельная копия)

Когда ты присваиваешь let b = a, JavaScript копирует значение из переменной a в новую переменную b. Они не связаны друг с другом.

Передача примитивов в функции

function increment(num) {
  num = num + 1;
  console.log("Внутри функции:", num); // 6
}

let value = 5;
increment(value);
console.log("Снаружи функции:", value); // 5 (не изменилось!)

Даже когда ты передаёшь параметр в функцию, JavaScript копирует значение. Изменение копии не влияет на исходную переменную.

Все примитивные типы

// Number
let num = 42;
let num2 = num;
num2 = 100;
console.log(num); // 42

// String
let str = "hello";
let str2 = str;
str2 = "world";
console.log(str); // "hello"

// Boolean
let bool = true;
let bool2 = bool;
bool2 = false;
console.log(bool); // true

// undefined
let x = undefined;
let y = x;
y = 10;
console.log(x); // undefined

// null
let a = null;
let b = a;
b = 5;
console.log(a); // null

Все примитивные типы передаются по значению — копируется их значение.

Объекты передаются по ссылке (важная тонкость!)

У сложных типов (объекты, массивы, функции) ситуация иная:

// ❌ Это НЕ передача по значению
let obj1 = { name: "Alice", age: 25 };
let obj2 = obj1; // копируется ссылка на объект, НЕ сам объект

obj2.name = "Bob";

console.log(obj1.name); // "Bob" - изменилось!
console.log(obj2.name); // "Bob"

// Почему?
// obj1 -> [ссылка на объект в памяти] <- obj2
// Обе переменные указывают на ОДИН И ТОТ ЖЕ объект

То есть JavaScript правильнее назвать "pass by sharing" — объекты передаются по ссылке, примитивы по значению.

Объекты в функциях

function modifyUser(user) {
  user.name = "Charlie"; // изменяет оригинальный объект
}

let person = { name: "Alice" };
modifyUser(person);
console.log(person.name); // "Charlie" - изменилось!

// Но если переназначить сам объект:
function reassignUser(user) {
  user = { name: "David" }; // создаёт новый объект
}

let person = { name: "Alice" };
reassignUser(person);
console.log(person.name); // "Alice" - не изменилось!

Это ключевое различие: ты можешь изменять свойства объекта, но если переназначить саму переменную, это не повлияет на исходный объект.

Визуальное объяснение

// Примитив (по значению)
let a = 5;
let b = a;
// a: [5]
// b: [5] (отдельная копия)

// Объект (по ссылке)
let obj1 = { x: 10 };
let obj2 = obj1;
// obj1: --->
//         |
// obj2: ---+---> { x: 10 } (один объект в памяти)

Частая ошибка: изменение параметра

// ❌ Проблема
function processArray(arr) {
  arr.push(4); // изменяет оригинальный массив!
}

let numbers = [1, 2, 3];
processArray(numbers);
console.log(numbers); // [1, 2, 3, 4] - неожиданно изменилось!

// ✅ Решение 1: создай копию
function processArray(arr) {
  const copy = [...arr]; // создаём копию
  copy.push(4);
  return copy;
}

let numbers = [1, 2, 3];
const result = processArray(numbers);
console.log(numbers); // [1, 2, 3]
console.log(result);  // [1, 2, 3, 4]

// ✅ Решение 2: не изменяй входные параметры
function processArray(arr) {
  const newArray = arr.slice();
  newArray.push(4);
  return newArray;
}

Как создавать копии

// Поверхностная копия (shallow copy)
const arr1 = [1, 2, 3];
const arr2 = [...arr1]; // новый массив

const obj1 = { name: "Alice" };
const obj2 = { ...obj1 }; // новый объект

// Глубокая копия (deep copy) для вложенных объектов
const deepCopy = JSON.parse(JSON.stringify(obj1));
// Или использовать структурированное клонирование
const deepCopy2 = structuredClone(obj1);

// Проблема с поверхностной копией
const user1 = { name: "Alice", address: { city: "NYC" } };
const user2 = { ...user1 }; // поверхностная копия

user2.address.city = "LA"; // изменит и user1!
console.log(user1.address.city); // "LA" - неожиданно изменилось!

// Нужна глубокая копия
const user3 = structuredClone(user1);
user3.address.city = "LA"; // user1 не изменится

Передача по значению в TypeScript

// Явная типизация помогает избежать ошибок
function updateUser(user: User): void {
  // ясно, что User — объект
  user.name = "Bob"; // может изменить оригинал
}

function createUser(userData: User): User {
  // возвращаем новый объект, не изменяя входной
  return { ...userData, id: generateId() };
}

Практический пример из React

// ❌ Проблема: мутируем состояние
function UserProfile() {
  const [user, setUser] = useState({ name: "Alice", scores: [10, 20] });

  const addScore = (score: number) => {
    user.scores.push(score); // мутирует существующий объект!
    setUser(user); // React не заметит изменение
  };
}

// ✅ Правильно: создаём новый объект
function UserProfile() {
  const [user, setUser] = useState({ name: "Alice", scores: [10, 20] });

  const addScore = (score: number) => {
    // создаём новый объект с новым массивом
    setUser({
      ...user,
      scores: [...user.scores, score]
    });
  };
}

Иммутабельность (Immutability)

Добрая практика — не изменять переданные параметры:

// ❌ Плохо: мутирует параметр
function processData(data: DataType[]): void {
  data.sort();
  data.map(item => item.value * 2);
}

// ✅ Хорошо: возвращает новый результат
function processData(data: DataType[]): DataType[] {
  return data
    .slice() // копия
    .sort()
    .map(item => ({ ...item, value: item.value * 2 }));
}

Резюме

  • Примитивные типы (число, строка, boolean и т.д.) передаются по значению — копируется их значение
  • Объекты передаются по ссылке — обе переменные указывают на один объект в памяти
  • Изменение объекта внутри функции влияет на оригинальный объект — нужно создавать копии
  • Избегай мутирования параметров — это делает код непредсказуемым
  • Используй иммутабельность — особенно в React, где это критично для обновления состояния