Изменчивость против неизменности в 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. Его можно абсолютно бесплатно скачать по ссылке выше ☺.