Прокачай свои знания о строках в JavaScript с этой статьей!
Короткая статья о том, как работают строки в JavaScript. Рассматривается неизменяемость строк, механизмы сравнения и оптимизация выделения памяти для строк.
Начнем с вопросов: что выведет этот код?
const str = "Hello";
str[2] = "a";
console.log(str);
А если заменить const
на let
?
let str = "Hello";
str[2] = "a";
console.log(str);
Попробуйте ввести этот код в консоль браузера и проверить, что получится.
В JavaScript строки являются неизменяемыми. Это означает, что независимо от того, объявлена ли переменная через let
или const
, значение не изменится, и в обоих случаях будет выведено "Hello"
.
Но что, если мы добавим оператор присваивания с конкатенацией строк:
const str = "Hello";
str += " World";
console.log(str);
Данный код выполнится с TypeError: Assignment to constant variable
, из-за того, что мы объявили строку как const
. Заменим его на let
:
let str = "Hello";
str += " World";
console.log(str);
В JavaScript строки копируются при присваивании значения из одной строки в другую. Следовательно, этот код выведет "Hello World"
. В конце статьи мы пошагово разберем, как работает такой код.
Давайте разберем копирование строк чуть подробнее. Что выведет этот код и почему?
const str1 = 'Hello';
const str2 = str1;
console.log(str1 === str2);
При копировании строки в JavaScript создается новая ссылка на объект строки, но сама строка не дублируется в памяти. Следовательно, при сравнении str1 === str2
будет выведено true
. Объясним подробнее:
-
Создание строки
'Hello'
: Выделение памяти для хранения строки'Hello'
. -
Присваивание значения другой переменной: Переменная
str2
получает ссылку на тот же объект строки в памяти, что и переменнаяstr1
. -
Сравнение переменных: При сравнении
str1 === str2
JavaScript сначала сравнивает значения ссылок, а не сами строки. Поскольку обе переменные ссылаются на один и тот же объект строки в памяти, сравнение вернетtrue
.
А если мы не будем копировать строку и создадим новую с таким же значением как у первой. Что выведет этот код, почему и как он работает?
const str1 = 'Hello';
const str2 = 'Hello';
console.log(str1 === str2);
-
При объявлении const
str1 = 'Hello'
в памяти выделяется место для хранения строки'Hello'
. -
Затем, при объявлении const
str2 = 'Hello'
, JavaScript оптимизирует использование памяти и создает только один объект строки для обеих переменных. Вместо того, чтобы выделять новое место в памяти для строки'Hello'
, JavaScript обнаруживает, что строка'Hello'
уже существует в памяти (в результате объявленияstr1
), и просто создает ссылку на эту же строку для переменнойstr2
. -
При выполнении
console.log(str1 === str2)
происходит сравнение переменныхstr1
иstr2
. Поскольку обе переменные ссылаются на один и тот же объект строки в памяти, сравнение вернетtrue
.
А что выведет код ниже и почему?
const str1 = 'Hello';
const str2 = 'Hello2';
console.log(str1 === str2);
В данном случае переменные str1
и str2
содержат разные строки: 'Hello'
и 'Hello2'
.
-
При объявлении
const str1 = 'Hello'
в памяти выделяется место для хранения строки'Hello'
. -
Затем, при объявлении
const str2 = 'Hello2'
, JavaScript создает новый объект строки для значения'Hello2'
и выделяет ему отдельное место в памяти. -
После этого, при выполнении
console.log(str1 === str2)
происходит сравнение переменныхstr1
иstr2
. Поскольку они ссылаются на разные объекты строк в памяти, сравнение вернетfalse
.
Разберем подробнее пример с конкатенацией строк:
const str1 = 'Hello';
const str2 = str1 + '2';
console.log(str1 === str2);
-
При объявлении
const str1 = 'Hello'
в памяти будет выделена память для строки'Hello'
. -
При объявлении
const str2 = str1 + '2'
происходит конкатенация строк. JavaScript создает новую строку, объединяя содержимоеstr1
(которая содержит'Hello'
) и строки'2'
. Поскольку строки в JavaScript неизменяемы, создается новый объект строки для результата конкатенации, в данном случае'Hello2'
. -
После этого, при выполнении
console.log(str1 === str2)
, посколькуstr1
содержит'Hello'
, аstr2
содержит'Hello2'
, они указывают на разные объекты строки в памяти, и сравнение вернетfalse
.