Поехали!
Строки — это не единственная проблема
Так как строки весьма интересны и в некотором смысле игривы (прямо как золотистый ретривер), их легко выбрать в качестве главного виновника этой путаницы с примитивами и объектами. Но как в итоге выясняется, в их банду также входят и многие другие примитивные типы. Таблица 15.1 показывает популярные встроенные типы Object, включая большинство виновников (Symbol и BigInt отсиживаются в стороне), которые, помимо прочего, замешаны и в связях с примитивами:
Табл. 15.1. Объектные типы, включая те, что представляют примитивы
Тип
Назначение
Array
Помогает хранить, извлекать и управлять наборами данных
Boolean
Выступает в роли обертки для примитива boolean; а также работает с помощью true и false
Date
Упрощает представление дат и работу с ними
Function
Позволяет вызывать заданный код
Math
Умник среди типов, расширяющий возможности работы с числами
Number
Выступает в качестве обертки для примитива number
RegExp
Предоставляет множество возможностей для сопоставления шаблонов в тексте
String
Выступает в качестве обертки для примитива string
Всегда при работе с логическими значениями, числами или строчными примитивами у нас есть доступ к свойствам, представленным их объектными эквивалентами. В ближайших разделах вы увидите, что конкретно при этом происходит.
Давайте все-таки выберем строки
Как и говорилось в предыдущих главах, обычно мы используем строки в форме литералов:
let primitiveText = "Homer Simpson";
Как видно из таблицы, строки тоже могут быть использованы как объекты. Есть несколько способов создания нового объекта, но в случае создания объекта для типа вроде строки чаще всего используется ключевое слово new, сопровождаемое String:
let name = new String("Batman");
String в данной ситуации не просто обычное слово. Оно представляет собой так называемую функцию-конструктор, которая используется исключительно для создания новых объектов. Аналогично наличию нескольких способов создания объектов есть несколько способов создания объектов String. Я же считаю, что достаточно знать один способ, который не следует использовать для их создания.
Как бы то ни было, главное отличие между примитивной и объектной формами строки — это существенное количество лишнего багажа, присущего объекту. На рис. 15.1 — визуальное представление нашего объекта String с именем name.
Рис. 15.1. Углубленный вид объекта String
Переменная name содержит указатель на текст "Homer Simpson". Нам также доступно все множество свойств и методов, присущих объекту String, включая те, что вы уже использовали ранее (indexOf, toUpperCase и пр.).
Мы сделаем обширный обзор этого визуального представления позднее, когда будем рассматривать объекты подробнее. Пока не беспокойтесь, если не совсем понимаете ее суть. Просто знайте, что объектная форма любого примитива несет в себе богатый функционал.
Почему это важно
Давайте вернемся к сбивающему с толку моменту. Наша строка — это примитив. Как может примитивный тип позволить обращаться к его свойствам? Дело в том, что JavaScript — весьма странный язык. Предположим, у нас есть следующая строка:
let game = "Dragon Age: Origins";
Очевидно, что переменная game — это строковый примитив, присвоенный конкретному тексту. Если мы захотим обратиться к length этого текста, то сделаем следующее:
let game = "Dragon Age: Origins";
console.log(game.length);
Как часть вычисления game.length JavaScript преобразует строковый примитив в объект. На короткое время наш приземленный примитив станет прекрасным объектом, чтобы мы могли выяснить его длину. Здесь следует помнить, что все это временно. Так как этот временный объект не имеет основы и ни к чему не привязан, то после выполнения своей миссии он удаляется и остается лишь результат вычисления length (число), а переменная game по-прежнему является строковым примитивом.
Такая трансформация происходит только с примитивами. Если мы создадим объект String, то он так и останется навсегда объектом. Представим следующий пример:
let gameObject = new String("Dragon Age: Origins");