Как стать автором
Обновить

Примитивы в JavaScript — это миф?

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров3.9K

Все мы знаем что в JavaScript есть ссылочные (Object), присваивающиеся по ссылке и примитивные типы данных (String, Number, Null и тд), присваивающиеся по значению. Но так ли это на самом деле? В этой статье с помощью небольшого эксперимента мы убедимся, что это не совсем так и посмотрим как "примитивные" типы данных на самом деле хранятся в памяти.

Создадим небольшой HTML файл:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<a class="la1"></a>
<body>
  <script>
    var word = "word".repeat(1000000);
    document.querySelector('.a1').innerHTML = word;
  </script>
</body>
</html>

Мы создаем переменную word в которой хранится строка, содержащая 1 миллион повторений слова "word"
Сделаем snapshot во вкладке Memory в браузере Chrome и посмотрим на память

Мы видим что наша огромная строка занимает 4Мб памяти

Далее добавим в наш HTML файл немного кода

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<a class="a1"></a>
<a class="a2"></a>
<body>
  <script>
    var word = "word".repeat(1000000);
    // Добавляем переменную word2
    var word2 = word;
    document.querySelector('.a1').innerHTML = word;
    // Отрисовываем ее значение во вторую ссылку 
    document.querySelector('.a2').innerHTML = word2;
  </script>
</body>
</html>

Как мы все много раз слышали, примитивные типы передаются по значению, соответственно в переменную word2 должна попасть полная копия значения, которое лежит в переменной word и составляет 4Мб. В итоге мы ожидаем увидеть увеличение памяти в 2 раза.

Давайте смотреть!

Но как так! Память, занимаемая строками не то что не увеличилась в 2 раза, она вообще не изменилась! И мы не наблюдаем второй строки, переменная word2 ссылается на тот же участок памяти, что и переменная word. Никакой копии не произошло. Попробуем по-другому.

Давайте создадим массив и добавим туда несколько значений

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<a class="a1"></a>
<body>
  <script>
    var word = "word".repeat(1000000)
    var arr = [word, word, word, word, word]
    for (let i = 0; i < arr.length - 1; i++) {
        document.querySelector('.a1').innerHTML += word;
    }
  </script>
</body>
</html>

Как мы видим, снова ничего не изменилось. Все 5 элементов массива ссылаются на один и тот же участок памяти.

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

Вывод

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

Теги:
Хабы:
Всего голосов 9: ↑5 и ↓4+3
Комментарии20

Публикации

Истории

Работа

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
26 октября
ProIT Network Fest
Санкт-Петербург
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань