Изменчивость против неизменности в JavaScript

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

Примитивные типы и ссылочные типы в JavaScript

Данные, присвоенные переменной JavaScript, могут быть двух типов: примитивного типа и ссылочного типа. Существует разница в том, как JavaScript обрабатывает эти два типа данных. Чтобы узнать, как они обрабатываются по-разному, давайте сначала поймем разницу между примитивными и ссылочными типами.

Примитивные типы

Примитивные типы — это простые атомарные фрагменты данных в JavaScript. Примитивные типы всегда сохраняются и доступны по значению переменной, а не как ссылка на другой объект. В JavaScript есть шесть примитивных типов:

  • неопределенный
  • нулевой
  • логический
  • номер
  • нить
  • символ

Ссылочные типы

Ссылочные типы — это не простые атомарные значения, а объекты, состоящие из нескольких назначенных им свойств. Они хранятся в памяти как ссылка, а не как независимые значения, присвоенные переменным. В JavaScript существует три типа ссылок:

  • объекты
  • массивы
  • функции

Как примитивные типы и ссылочные типы хранятся в памяти

То, как примитивные и ссылочные типы хранятся в памяти, является основой того, чем они отличаются друг от друга. Давайте рассмотрим несколько примеров и попробуем понять, как они по-разному используют память.

Использование памяти примитивными типами

Как было сказано ранее, примитивные типы хранятся в виде одного атомарного значения, присвоенного переменной в памяти. Давайте посмотрим на этот пример:

Глядя на приведенный выше пример, я создал переменную name и присвоил ей значение john . Теперь JavaScript сохранит это как одно атомарное значение в памяти. Теперь, если я создам новую переменную name2 и присвою ей значение переменной name, JavaScript создаст новое пространство в памяти, выделит то же значение переменной name и присвоит его переменной name2. Новое значение, присвоенное переменной name2, полностью отделено от переменной name и не имеет к ней никакой ссылки.

Использование памяти ссылочными типами

Ссылочные значения — это объекты, хранящиеся в памяти, и ссылки на объекты вместо выделенных мест в памяти, в отличие от примитивных типов. Давайте рассмотрим следующий пример, чтобы лучше понять, как ссылочные типы сохраняются в памяти с помощью JavaScript.

Давайте просто объявим переменную с именем person, которая будет содержать объект, содержащий name и age объекта человека. Теперь я продолжу и создам еще одну переменную с именем person2 и назначу ей тот же объект person. Здесь все начинает отличаться от примитивных типов. В этом случае JavaScript сохранит объект person2 просто как ссылку на объект person.

Если вы посмотрите на это изображение, вы поймете, что здесь JavaScript фактически указывает на тот же объект в памяти. Хотя он создал новую переменную в качестве значения, эта переменная просто ссылается на тот же объект person, который мы создали ранее.

Понимание неизменности и изменчивости примитивных и ссылочных типов в JavaScript

Поскольку теперь мы разобрались с примитивными и ссылочными типами в JavaScript, мы можем легко понять концепцию изменчивости и неизменности в JavaScript. Изменчивость может быть изменена или добавлена, где неизменяемость означает что-то, что нельзя изменить или добавить. К примитивным значениям в JavaScript нельзя ничего добавить, их можно только переназначить, и, следовательно, все примитивные значения в JavaScript неизменяемы. Давайте посмотрим на это на примере.

Расширяя наш предыдущий пример с примитивными типами, давайте выведем значения обеих наших переменных, то есть name и name2, в консоль и посмотрим, что мы получим. Как и ожидалось, обе переменные возвращают значение john. Теперь давайте переназначим name2 в doe, а затем снова выведем значения обеих переменных в консоль. Теперь вы видите, что значение только name2 было переназначено JavaScript на doe, но переменная name не изменилась. Это показывает, что JavaScript обрабатывает эти 2 переменные по отдельности, хотя name2 изначально было скопировано из переменной name. Это доказывает, что примитивные значения в JavaScript, в данном случае строки, неизменяемы.

Попробуем воспроизвести тот же пример и для ссылочных типов. Продолжая наш предыдущий пример, давайте напечатаем значения объектов person и person2 в консоль и посмотрим, что мы получим.

Мы видим два напечатанных на консоли объекта с одинаковыми свойствами. Теперь я изменю одно из свойств объекта person2 и снова выведу их в консоль.

Вы видите, что JavaScript изменился person, а также person2. Это связано с тем, что объект person2 был создан путем ссылки на объект person. При использовании ссылочных типов JavaScript создает ссылку на тот же объект, и объект остается изменяемым. Поскольку объект является изменяемым, его можно изменить или добавить новое свойство.

Оператор спреда

Оператор распространения был представлен в ES6 (подробнее о ES6) и позволяет безопасно копировать объекты и создавать новый экземпляр объекта вместо того, чтобы просто ссылаться на предыдущий объект. Давайте посмотрим на тот же пример и посмотрим, как мы можем скопировать объект и сохранить новый экземпляр объекта переменной.

Давайте возьмем тот же объект person и вместо того, чтобы присваивать его непосредственно переменной на этот раз, воспользуемся оператором распространения для его копирования. Оператор распространения можно использовать, поставив префикс из трех точек перед объектом, который вы хотите скопировать, и инкапсулировать его, используя синтаксис буквального объекта. Таким образом, JavaScript создает новый объект и сохраняет его в переменной person2. Давайте попробуем изменить одно из свойств person2 . Я изменю имя на doe . Теперь давайте выведем оба объекта в консоль и посмотрим, что у нас получится. Видите ли, на этот раз мы изменили только свойство имени объекта person2, а не объекта person. Это связано с тем, что person2 был создан и сохранен как новый объект с использованием оператора распространения, а не как ссылка на объект person.

Получите доступ к большему количеству таких историй на Cloudaffle

Спасибо за чтение, и, надеюсь, это было полезно!

Я создал обширную шпаргалку по JavaScript. Это было сделано таким образом, чтобы вам было легко обращаться к каждому свойству и методу для различных объектов JavaScript. Его можно абсолютно бесплатно скачать по ссылке выше ☺.

Если этот пост был полезен, пожалуйста, нажмите кнопку хлопка 👏 несколько раз, чтобы выразить свою поддержку! 👇