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

Комментарии 20

А с каких пор строки стали примитивами?

Такова терминология JavaScript.

https://learn.javascript.ru/primitives-methods
ЦИТАТА:
Есть 7 примитивных типов: string, number, boolean, symbol, null, undefined и bigint.

https://developer.mozilla.org/en-US/docs/Glossary/Primitive
ЦИТАТА:
There are 7 primitive data types:
string
number
bigint
boolean
undefined
symbol
null

В JS как всегда всё странно. Строки в JS бывают примитивами или объектами. Интерфейс у них при этом одинаковый:

на строковых примитивах возможно использовать методы объекта String. В контекстах, когда на примитивной строке вызывается метод или происходит поиск свойства, JavaScript автоматически оборачивает строковый примитив объектом и вызывает на нём метод или ищет в нём свойство.

Но проблемы всё же бывают:

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

Авторский код "word".repeat(1000000); очевидно возвращает объект, который далее передаётся по ссылке. Чтобы получить примитив строки из объекта строки, нужно использовать метод valueOf() - "word".repeat(1000000).valueOf().

@Vindrix попробуйте начать читать мануалы.

Метод repeat возвращает примитивную строку, поэтому valueOf() было бы актуально к

let objStr = new String("word");
let primStr = objStr.valueOf();

Нет, это совсем другое. Вы говорите про "объектные обертки" к примитивным типам. А данная статья именно о примитивных типах, которые под капотом нифига не примитивные.

"word".repeat(1000000); возвращает именно строку, а не объектную обертку, и valueOf тут ничего не поменяет.

Ну вообще не стоит создавать инстансы строк через new, а то можно на тех же проверках типов полететь.

Это что? Незнание того что существуют неизменяемые типы? Строка это неизменяемый ссылочный тип.

Выглядит как заметка об иммутабельности строк. В c#, например, интернирование строк тема достаточно интересная, но большая часть темы уже касается не простого запихивания одних и тех же констант в массив, а о поведении при операциях со строками, вроде склеивания (var word ="word" и var word2 = "wo" + "rd" - это и то же?).

Нет не тоже, в таком случае в памяти heap создастся три значения

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

Строки как объекты

Почти всё в JavaScript является объектами. Когда вы создаёте строку, например:

let string = 'This is my string';

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

Так по мне семантически это верно. Думаю так легче новичкам объяснять чем заморачивать им такими деталями. Хотя очень полезно такое знать.

Новичкам возможно и не стоит заморачиваться помимо не использования new String(…), а потом вместе с теми же скрытыми классами узнать, когда будет интересно.

То что строки на самом деле объекты, в общем-то интуитивно понятно. Меня больше удивило, что даже числа могут быть объектами. "Истинных" примитивов в JS немного, вроде только целые 32-разрядные числа со знаком

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

Я пробовал это
Number.prototype.myFunc = function () {return this}
var t = 2
t.myFunc() === t.myFunc() // false


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

Попробуйте в строгом режиме.

Вывод некорректный по итогу. А эксперимент годный. Я как раз недавно пытался по новой погрузиться в эту тему(удалось не до конца, пока на паузе).

Стоит заметить, что сразу можно откинуть источники инфы, которые пользуются определением "ссылочный/примитивный". Видимо это тянется с ES 5 https://262.ecma-international.org/5.1/#sec-4.3.2

В новой спеке используются понятия " Values without identity/ Values with identity " и то ...
https://tc39.es/ecma262/multipage/notational-conventions.html#sec-identity

Внимание, ниже мой вывод, который может быть вообще некорректный и требует валидации.

Как я понял каждое значение имеет некие характеристики, которым можно описывать само значение(в том числе ссылка на значение в памяти). И если с так называемыми примитивами эти характеристики легко получить, то с объектами - нет.

Если я ошибся, то поправьте, но только с ссылками на офф доку, потому что тема оч интересная

Согласно спецификации JS не существует таких понятий как примитивный или ссылочный тип данных (привет @demimurych).

"JavaScript движки оптимизируют использование памяти"
Это верно. Но здесь, с большой вероятностью, речь идет о применении оптимизационного механизма на стадии компиляции кода внутри движка (к сожалению, наименования оптимизационного правила на вскидку не припомню).

Ну тут скорее вопрос терминологии. И о каком уровне абстракции идёт речь. На уровне семантики языка строка - примитивный тип, тут всё нормально. А под капотом да, ситуация посложнее.

Кстати, мне недавно попадалась информация, что вроде бы V8 по каким-то своим причинам эмулирует floating point арифметику! То есть это не нативные операции CPU, а числа на самом деле тоже как бы объекты. Сам я это утверждение пока не проверял, руки не дошли. Если кто-то в курсе как на самом деле - сообщите.

Забавная статья, для джуна сойдет)) вообще ссылаться на learnjs (это было в коментах, а не в статье), это плохой пример убедить читателей в компетентности. В спеке ecma, если открыть про строки, тут же прочитаете, что они имутабельны. Из этого можно сделать вывод, а для чего в памяти хранить копии одного значения, если каждое есть имутабельно? Подумав, можно придти к выводу, что смысла нет) а значит как то они все же передаются по ссылке. Тут стоит еще капнуть глубже и понять, что в js не существует переменных как таковых, вы не найдете такого термина в спецификации. Все, что вы называете переменными в js на самом деле называется идентификаторами которые всегда по ссылке соединены со значением. Исключениями, в рамках реализации различных рантаймов, могут быть числа. В v8 числа до 2^31-1 хранятся в smi а не в heap. Вы можете ознакомится, как например можно запустить node js с флагом --allow-natives-syntax, и с помощью команды %DebugPrint посмотреть на что и как ссылаются ваши идентификаторы. Это перевернет Ваш мир)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории