Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Передача за значенням і за посиланням». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Примітиви (`number`, `string`, `boolean`, `null`, `undefined`, `symbol`, `bigint`) копіюються за значенням, а об'єкти (`object`, `array`, `function`, `Date`, `Map`, `Set`) копіюються за посиланням.** Під час присвоєння примітива створюється нова незалежна копія даних, тому зміна однієї змінної не зачіпає іншу. Під час присвоєння об'єкта копіюється лише вказівник на ту саму ділянку пам'яті, тому обидві змінні бачать одні й ті самі зміни. ```javascript let a = 5; let b = a; // копія значення b = 10; console.log(a); // 5, не змінився const user1 = { name: 'Maria' }; const user2 = user1; // копія посилання user2.name = 'Alex'; console.log(user1.name); // "Alex" ``` **Ключове:** примітив копіює дані, об'єкт копіює лише посилання, тож для незалежного об'єкта потрібна явна копія (`{ ...obj }` або глибоке клонування).Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**«За значенням» означає, що змінна зберігає саме значення, і під час копіювання створюється нова незалежна копія даних; «за посиланням» означає, що змінна зберігає лише вказівник на місце в пам'яті, і копіюється саме цей вказівник.** У JavaScript за значенням поводяться примітиви, а за посиланням, об'єкти та всі складні структури даних. ## Теорія ### TL;DR - Примітиви (`number`, `string`, `boolean`, `null`, `undefined`, `symbol`, `bigint`) передаються за значенням. - Об'єкти (`object`, `array`, `function`, `Date`, `Map`, `Set` тощо) передаються за посиланням. - Копія примітива повністю незалежна: зміна `b` не впливає на `a`. - Копія об'єкта, це та сама структура в пам'яті: зміна через одну змінну видно через іншу. - Щоб отримати незалежний об'єкт, потрібна поверхнева (`{ ...obj }`) або глибока копія. ### Швидкий приклад ```javascript // за значенням let a = 5; let b = a; // копіюється значення 5 b = 10; console.log(a); // 5, не змінився console.log(b); // 10 // за посиланням const user1 = { name: 'Maria' }; const user2 = user1; // копіюється ПОСИЛАННЯ, а не сам об'єкт user2.name = 'Alex'; console.log(user1.name); // "Alex" console.log(user2.name); // "Alex" ``` ### Що означає «за значенням» (by value) > Змінна зберігає **саме значення**, а не посилання на нього. > Під час копіювання створюється **нова незалежна копія даних**. За значенням передаються примітиви (прості типи даних). До них належать: - `number` - `string` - `boolean` - `null` - `undefined` - `symbol` - `bigint` ```javascript let a = 5; let b = a; // копіюється значення 5 b = 10; console.log(a); // 5 <- не змінився console.log(b); // 10 ``` `a` і `b` тепер два **незалежні значення**, і зміна `b` не впливає на `a`. ### Що означає «за посиланням» (by reference) > Змінна **не зберігає сам об'єкт**, вона зберігає **посилання (вказівник)** на місце в пам'яті, де цей об'єкт лежить. За посиланням передаються всі **об'єкти та складні структури даних**: - `object` - `array` - `function` - `Date`, `Map`, `Set` і так далі ```javascript const user1 = { name: 'Maria' }; const user2 = user1; // копіюється ПОСИЛАННЯ, а не сам об'єкт user2.name = 'Alex'; console.log(user1.name); // "Alex" console.log(user2.name); // "Alex" ``` Обидві змінні вказують на **один і той самий об'єкт** у пам'яті, тому зміна `user2` змінює і `user1`. Візуально це виглядає так: ```text +------------+ | user1 | --+ +------------+ | v { name: "Maria" } ^ +------------+ | | user2 | --+ +------------+ ``` ### Приклад з масивом Масив, це теж об'єкт, тож для нього діє те саме правило: ```javascript const arr1 = [1, 2, 3]; const arr2 = arr1; arr2.push(4); console.log(arr1); // [1, 2, 3, 4] console.log(arr2); // [1, 2, 3, 4] ``` Обидва масиви, це **один і той самий об'єкт** у пам'яті. ### Як створити копію об'єкта і не тягнути посилання Якщо потрібен **новий незалежний об'єкт**, дані треба явно **скопіювати**. Поверхнева копія (spread): ```javascript const user1 = { name: 'Tim', age: 25 }; const user2 = { ...user1 }; // оператор spread user2.name = 'Alex'; console.log(user1.name); // "Tim" console.log(user2.name); // "Alex" ``` Глибока копія (для вкладених об'єктів): ```javascript const user1 = { name: 'Tim', address: { city: 'Kyiv' } }; const user2 = JSON.parse(JSON.stringify(user1)); // глибоке клонування user2.address.city = 'Lviv'; console.log(user1.address.city); // "Kyiv" console.log(user2.address.city); // "Lviv" ``` ### Стек, купа і підсумкові таблиці | Тип | Де зберігається | Що відбувається під час копіювання | | --- | --- | --- | | Примітив (by value) | у **стеку** (stack) | створюється **нова копія** | | Об'єкт (by reference) | у **купі** (heap) | копіюється **посилання** на те саме місце | | Тип даних | Передача | Приклад | | --- | --- | --- | | `string`, `number`, `boolean`, `null`, `undefined`, `symbol`, `bigint` | **за значенням** | `let a = 5; let b = a;` | | `object`, `array`, `function`, `Date`, `Map`, `Set` | **за посиланням** | `let obj2 = obj1;` | Коротко: - **За значенням** створюється **копія даних**. - **За посиланням** копіюється **вказівник** на той самий об'єкт. - Саме тому зміна одного об'єкта **впливає** на інший, якщо вони пов'язані посиланням. ### Типові помилки - Вважати, що `const` захищає вміст об'єкта. `const` забороняє перепризначити змінну, але не забороняє змінювати поля об'єкта, на який вона вказує. - Робити `const copy = original` для об'єкта і думати, що це копія. Це друга назва для того самого об'єкта. - Плутати поверхневу копію з глибокою: `{ ...user }` копіює лише верхній рівень, вкладені об'єкти залишаються спільними. - Використовувати `JSON.parse(JSON.stringify(obj))` бездумно: цей спосіб втрачає `undefined`, функції, `Symbol`, перетворює `Date` на рядок і ламається на циклічних посиланнях. Для складних випадків краще `structuredClone(obj)`. - Порівнювати об'єкти через `===` і чекати `true`: `{ a: 1 } === { a: 1 }` дає `false`, бо це два різні посилання.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.