У меня была возможность пересмотреть свою ментальную модель отношений между переменными и ценностями. Это помогло мне лучше понять такие концепции JavaScript, как мелкое копирование.

Поверхностное копирование происходит, когда вы клонируете переменную, которая имеет значение объекта, присваивая ее другой переменной. Изменение объекта через одну переменную влияет на другую переменную.

Чтобы исследовать это глубже, есть несколько утверждений о JavaScript, которые мы должны иметь в виду:

Чтобы исследовать это глубже, есть несколько утверждений о JavaScript, которые мы должны иметь в виду:

  1. Все примитивные значения уже существуют, и каждое значение существует один раз.
  2. Мы можем создавать только непримитивные значения.
  3. Правая часть присваивания всегда возвращает значение. [например: let age = 10*3, значение, на которое указывает age, равно 30, а не 10*3.]
  4. Каждый раз, когда используется литерал объекта {}, создается новое значение объекта. [например: Object.is({}, {}) равно false.]
  5. Объект не может иметь два свойства с одинаковыми значениями.

Давайте посмотрим на этот фрагмент кода, используя примитивные типы.

Создание копий с помощью метода, описанного выше, прекрасно работает с примитивными типами значений, такими как Number и String. Это связано с первым утверждением «Все примитивные значения уже существуют, и каждое значение существует один раз».

В этой статье я буду использовать эскизы и текст для пошаговых фрагментов кода. Давайте рассмотрим это для приведенного выше фрагмента.

  1. У нас есть переменная a, которая указывает на числовое значение 2.
  2. У нас есть еще одна переменная b, которая указывает на значение 2 a.
  3. В этот момент a и b представляют одно и то же значение 2.
  4. b получает новое значение 3 и больше не указывает2.
  5. a и b указывают на 2 и 3 соответственно.

Эти представления вызвали у вас какие-то лампочки или это было очевидно?

Теперь давайте рассмотрим другой пример, но на этот раз мы будем рассматривать непримитивные типы, такие как объекты. Можете ли вы угадать, что будет зарегистрировано в консоли?

Это вывод из моей консоли, и вы тоже можете попробовать.

Если вы угадали Ibadan, результат может вас шокировать. Однако, если вы угадали Lagos , то вы либо хорошо разбираетесь в значениях и свойствах, либо знаете их как JavaScript.

Может возникнуть соблазн подумать, что line 5создает новое значение объекта для son.address, но это не так. Если вы помните, одно из утверждений гласит: «Каждый раз, когда используется литерал объекта {}, создается новое значение объекта».

Глядя на скетч ниже, мы видим, что были созданы только 3 значения объекта, family.address и son.address указывают на один и тот же объект. Каждый раз, когда свойство изменяется в значении Object для address, family.address и son.address изменяются, поскольку они указывают на один и тот же объект.

  1. family указывает на новое значение объекта, которое содержит только одно свойство address.
  2. Свойство address указывает на новое значение объекта, которое имеет свойство city и указывает на строковое значение Ibadan.
  3. son указывает на новое значение объекта и имеет свойство address.
  4. address указывает на то же значение объекта, которое было создано на шаге 2, и на его свойства.
  5. son.address.city обновляется и указывает на Lagos.
  6. Поскольку son.address и family.address указывают на одно и то же значение объекта, изменение свойств этого объекта влияет на оба. Вы можете проверить это, проверив вывод Object.is(son.address, family.address) в консоли.
  7. Выход для family.address.city теперь Lagos. Вы можете убедиться в этом, следуя стрелкам на скетче для example2.js.

Давайте рассмотрим еще один пример, чтобы закрепить то, что мы обсуждали. Можете ли вы угадать вывод этого фрагмента?

У нас есть предпосылка, аналогичная предыдущему примеру. Помня обо всех утверждениях, приступим к наброску.

  1. У нас есть переменная family, которая указывает на новое значение объекта с двумя свойствами: name и address.
  2. name указывает на строковое значение Madueke, а address указывает на новое значение объекта, которое имеет свойство city и указывает на строковое значение Ibadan.
  3. Далее у нас есть переменная son, которая указывает на другое значение объекта с тремя свойствами: name, surname и address.
  4. son.name указывает на строковое значение Adetola.
  5. son.surname указывает на то же значение, что и family.name.
  6. son.address указывает на то же значение, что и family.address. Попробуйте Object.is(son.address, family.address) в своей консоли.
  7. son.address.city обновляется, city теперь указывает на Lagos, а это означает, что family.address.city также указывает на Lagos.
  8. family.name теперь указывает на новое значение объекта со свойством surname.
  9. Значение, на которое указывает son.surname, не изменяется, поскольку его значение было определено до того, как family.name было переназначено.

Резюме

Присвоение переменных другим переменным или свойствам, которые указывают на объекты, не создает новое значение Object для переменной. Вместо этого переменная указывает на существующее значение объекта, что означает создание поверхностной копии. Если объект мутирует, все переменные, указывающие на значение объекта, также изменятся.

Эта идея также применима к массивам, поскольку массивы являются объектами. Попробуйте typeof [] в консоли.

Упражнение:

Каков результат этого?

PS: Вы можете создать скетч для фрагмента кода, как я сделал выше, а также просмотреть примеры.

Поделитесь своими ответами в комментариях или отправьте ответ мне в Твиттере через эту тему.

В восторге от этого изменения в моем процессе мышления JS и улучшения моих ментальных моделей в JS и программировании в целом. Какие вещи, которые вы узнали о программировании, вы хотели бы знать, когда начинали?