@user2080

Какие на самом деле типы данных в javascript?

Здравствуйте!

Как я понимаю в js два основных типа данных(условно). Это примитивные типы данных и обьекты.

Примитивы иммутабельны, к примеру у нас есть строка, нам нужно добавить еще несколько символов к ней, следовательно выполняем конкатенацию.
let str = 'Hello'
let result = str + 'Vova'


1. Что происходит с типом данных когда str конкатинируется со строкой 'Vova' ?

Как я понимаю переменная str с типом данным(примитивным) в следствии конкатенации, создается новое значение (все тот же примитив), и который уже никаким образом не относится к str(имею ввиду не ссылающееся как объект по ссылке),

2. Вопрос вот в чем, так ли примитивы перезаписываются если с ними выполняются какие-то операции? Меня интересует сам алгоритм создания, что происходит внутри.

3. Являются ли примитивные типы объектами?
  • Вопрос задан
  • 284 просмотра
Решения вопроса 1
bingo347
@bingo347 Куратор тега JavaScript
Crazy on performance...
Как я понимаю в js два основных типа данных

Согласно спеке в JS есть 8 типов данных:
  • object - все объекты и функции (в реальности во всех имплементациях у функций свой тип function)
  • string - строки
  • boolean - логические значения (true и false)
  • number - числа с плавающей запятой двойной точности (в других языках это double или float64)
  • bigint - целые числа (int64) с поддержкой длинной арифметики
  • symbol - спец тип, каждое значение которого уникально
  • undefined - юнит тип с единственным значением undefined, значение по умолчанию во многих случаях
  • null - юнит тип с единственным значением null (в реальности во всех имплементациях null имеет тип object), задумывался и используется как аналог null pointer/null reference в других языках


Что происходит с типом данных когда str конкатинируется со строкой 'Vova' ?
с типом данных ничего не происходит. Значение получается новое, по крайней мере так должно быть согласно спеке и так все выглядит для рядового js разработчика.
На самом деле самый распространенный js движок v8 именно со строками делает под капотом разную магию, зная, что строки никогда не меняются он умеет их представлять в виде массива срезов (множества кусочков лежащих в разных местах), избегая тем самым дорогого копирования памяти. В данном примере result будет состоять из двух срезов, которые указывают на представление кода в памяти, притом первый кусок будет указывать на ту же память что и str. Но если result "доживет" до момента, когда сборщик мусора будет делать дефрагментацию памяти, то после нее он уже будет указывать на целую самостоятельную строку.

Вопрос вот в чем, так ли примитивы перезаписываются если с ними выполняются какие-то операции? Меня интересует сам алгоритм создания, что происходит внутри
Примитивы никогда не перезаписываются, по крайней мере пока они "живы" (пока сборка мусора не признает их мусором в виду отсутствия ссылок на память где они лежат). Все манипуляции с переменными под капотом почти всегда (о том когда нет - напишу ниже) являются простыми манипуляциями над указателями (ссылками).

Являются ли примитивные типы объектами?
С точки зрения спеки - нет, не являются. У них должны появляться объектные обертки в момент обращения к их полям (через точку или квадратные скобки).
На деле, если сделать как в спеке - все будет жутко тормозить. Поэтому в v8 почти все является объектом (правда не совсем таким, как мы видим объекты со стороны js), а соблюдение спеки для примитивных типов достигается через иммутабельность.
Исключением являются null и undefined, у которых нет ни полей, ни прототипа. Для них хранится только информация о типе.
Так же после оптимизаций jit компилятора числа могут избавится от объектных оберток, когда оптимизируемый код их не использует, тем самым избавляясь от разыменовывания указателя, при этом bigint может превратится в int64, а number в float64 или int32 в зависимости от использования. Так же, массивы состоящие только из чисел одного типа могут быть сведены к настоящим массивам из чисел, но этого эффекта можно достичь и до оптимизаций, если использовать типизированные массивы.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
lssssssssssl
@lssssssssssl
1. Просто появляется новая result переменная с типом string, которая никакого отношения к str не имеет.
Тип переменной в js определяется в момент присваивания, а не в момент объявления. Каждый раз, когда ты присваиваешь ей новое значение, определяется её тип.

2. "Переменная" – это просто свойство специального внутреннего объекта: Environment Record. «Получить или изменить переменную», означает, «получить или изменить свойство этого объекта».

3. Нет. Спутать в этом случае может то, что в js есть возможность вызвать метод у примитива (К примеру, toUpperCase() у строки), это возможно потому что у каждого примитива имеется "объект-обёртка", который появляется в момент обращения к переменной(После удаляется).
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы