Як зрозуміти посилання проти значення в JavaScript

У цій статті розглядається поведінка різних типів даних JavaScript, коли вони присвоюються змінній. Залежно від типу даних пам’ять виділяється для зберігання по-різному. Він може зарезервувати новий простір для зберігання копії значення, а може взагалі не створити копію і просто вказати на існуюче значення (посилання).

Ось мої нотатки, зроблені під час проходження курсу Javascript30 Весом Босом.

Числа, рядки та булеві значення

В JavaScript Примітивні типи , такі як undefined, null, string, number, booleanі symbolпередаються за значенням.

let name = ‘Marina’;let name2 = name;
console.log({name, name2}); >> { name: ‘Marina’, name2: ‘Marina’ }
name = ‘Vinicius’;
console.log({name, name2});>> { name: ‘Vinicius’, name2: ‘Marina’ }

Коли призначена змінна name, простір у пам'яті з адресою 0x001зарезервовано для зберігання цього значення. Потім змінна nameвказує на цю адресу. Потім змінна name2встановлюється рівною name. Новий простір у пам'яті з новою адресою 0x002виділяється і зберігає копію значення, що зберігається в адресі, на яку nameвказує.

Отже, кожного разу, коли ми хочемо змінити значення name, значення, яке зберігається, name2не буде змінено, оскільки його копія зберігається в іншому місці.

Об'єкти та масиви

Об'єкти в JavaScript передаються за посиланням. Коли встановлено більше однієї змінної для зберігання або object, arrayабо function, ці змінні будуть вказувати на той самий виділений простір у пам'яті.

const animals = ['Cat', 'Dog', 'Horse', 'Snake'];
let animals2 = animals;console.log({animals, animals2});>>{ animals: ['Cat', 'Dog', 'Horse', 'Snake'], animals2: ['Cat', 'Dog', 'Horse', 'Snake']}
animals2[3] = 'Wale';console.log(animals, animals2);>>{ animals: ['Cat', 'Dog', 'Horse', 'Wale'], animals2: ['Cat', 'Dog', 'Horse', 'Wale']}

Коли animalsналаштовано зберігати масив, виділяється пам’ять і адреса пов’язується з цією змінною. Тоді animals2встановлюється рівним animals. Оскільки animalsзберігає масив, замість того, щоб створити копію цього масиву та нову адресу в пам'яті, animals2просто вказується на той самий об'єкт у існуючій адресі. Таким чином, будь-які внесені зміни animals2будуть відображатися animals, оскільки вони вказують на одне і те ж місце.

Ви побачите однакову поведінку для об’єктів:

const person = { name: 'Marina', age: 29};
let femme = person;femme.age = 18;
console.log({person, femme});>>{ person: { name: 'Marina', age: 18 }, femme: { name: 'Marina', age: 18 }}

Копіювання об'єктів та масивів

Оскільки простого призначення недостатньо для створення копії об'єкта, цього можна досягти іншими підходами:

Масиви

фрагмент ()

let animals2 = animals.slice();animals2[3] = 'Shark';

concat ()

let animals3 = [].concat(animals);animals3[3] = 'Tiger';

розповсюдження (ES6)

let animals4 = [...animals];animals4[3] = 'Lion';

Зміни торкнуться лише модифікованого об’єкта:

console.log({animals, animals2, animals3, animals4});>>{ animals: ['Cat', 'Dog', 'Horse', 'Snake'], animals2: ['Cat', 'Dog', 'Horse', 'Shark'], animals3: ['Cat', 'Dog', 'Horse', 'Tiger'], animals4: ['Cat', 'Dog', 'Horse', 'Lion']}

Об'єкти

призначити ()

let human = Object.assign({}, person, { age: 20 });
console.log(person, human);>>{ person: { name: 'Marina', age: 29 }, human: { name: 'Marina', age: 20 }}

Глибокий клон

Важливо зазначити, що ці методи глибиною лише один рівень. Для глибоких клонів існує метод, який не відповідає вимогам. Використовуйте обережно.

let femme3 = JSON.parse(JSON.stringify(person));femme3.name = 'Leslie';
console.log(person, femme3);>>{ person: { name: 'Marina', age: 29 }, femme3: { name: 'Leslie', age: 29 }}

Список літератури

  • WesBos - Javascript 30
  • Ви не знаєте JS: Сфера застосування та закриття Кайла Сімпсона

Спочатку опубліковано на marina-ferreira.github.io.