W3docs

Методы примитивов в JavaScript

Узнайте, как примитивы JavaScript — строки, числа, boolean, символы и bigint — вызывают методы через временные объекты-обёртки, с примерами и типичными ошибками.

Введение в примитивы и объекты JavaScript

В JavaScript почти всё, что вы пишете, является либо примитивом, либо объектом. Понимание разницы между ними — и хитрого механизма, позволяющего примитивам вести себя как объекты, — это одна из основ языка.

Примитив — это простейшее, неделимое значение. Существует семь примитивных типов: числа, строки, boolean, undefined, null, символы и bigint. Объект — это коллекция свойств и методов.

Вот задача, которую решает эта страница: string является примитивом без методов, однако "hello".toUpperCase() работает. Как значение без методов может вызвать метод? Ответ — объекты-обёртки, и эта глава объясняет, как именно они работают.

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

Что делает примитивы уникальными

Примитивы отличаются от объектов в трёх важных отношениях.

1. Неизменяемость. После создания примитивное значение нельзя изменить. Операция над string никогда не редактирует оригинальную строку — она возвращает совершенно новую строку. Попытка присвоить значение символу ничего не даёт (а в строгом режиме выбрасывает исключение):

javascript— editable

2. Хранение по значению. Примитив хранится непосредственно в переменной. При копировании копируется само значение, поэтому две переменные полностью независимы:

javascript— editable

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

3. Простота и лёгковесность. Примитив не несёт собственных свойств или методов, что делает его быстрым в создании и сравнении. boolean вроде let flag = true; — это просто значение, без накладных расходов, которые были бы у объекта.

Объекты в JavaScript: сравнение

Объекты — более сложная структура. В отличие от примитивов, они:

  • Изменяемы — их содержимое можно менять после создания.
  • Ссылочные типыобъекты хранятся и копируются по ссылке, а не по значению.
  • Универсальны — они могут содержать функции, массивы и другие объекты.

Как примитивы вызывают методы: объекты-обёртки

Так как же работает "hello".toUpperCase(), если у строки нет методов? Когда вы обращаетесь к свойству или методу примитива, JavaScript:

  1. Создаёт временный объект-обёртку соответствующего типа, содержащий это примитивное значение.
  2. Считывает из этой обёртки запрошенный метод или свойство.
  3. Выполняет его и возвращает результат.
  4. Немедленно уничтожает объект-обёртку.

Весь этот процесс происходит за кулисами и сильно оптимизирован движком, поэтому он практически бесплатен. Главный вывод: сам примитив никогда не изменяется и никогда не превращается в object постоянно — обёртка существует лишь на время одного выражения.

Конструкторы-обёртки

Пять примитивных типов имеют соответствующий встроенный конструктор-обёртку, предоставляющий их методы:

  • String — для строковых примитивов.
  • Number — для числовых значений.
  • Boolean — для boolean-значений.
  • Symbol — для символов.
  • BigInt — для bigint.

null и undefined не имеют никакой обёртки, поэтому обращение к свойству на них выбрасывает TypeError (например, null.toString() не работает).

Методы string

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

javascript— editable

Обратите внимание: length — это свойство, а не метод, поэтому у него нет скобок. toUpperCase() возвращает новую строку и оставляет greeting неизменной, в соответствии с правилом неизменяемости выше.

Методы number

Числа получают методы от обёртки Number. Часто используется toFixed(), который округляет до заданного числа десятичных знаков:

javascript— editable

Два момента, на которые стоит обратить внимание. Во-первых, toFixed() возвращает string, а не числоtypeof (3.14159).toFixed(2) равно "string". Во-вторых, чтобы вызвать метод непосредственно на числовом литерале, нужны дополнительные скобки или пробел: 255..toString(16) тоже работает, но 255.toString(16) является синтаксической ошибкой, поскольку парсер читает первую точку как десятичную.

Методы boolean

Булевы значения могут использовать обёртку Boolean, чаще всего просто toString():

javascript— editable

Методы Symbol

Символы, уникальный примитивный тип, получают методы от обёртки Symbol:

javascript— editable

Здесь необходимо явно вызывать toString() — символы намеренно не выполняют автоматическое преобразование в string в строковых контекстах (например, "" + sym), что в противном случае выбросило бы TypeError.

Методы BigInt

BigInt, предназначенный для целых чисел, слишком больших для обычного типа Number, получает методы от обёртки BigInt:

javascript— editable

Значение передаётся здесь как string, потому что запись его в виде числового литерала превысила бы диапазон безопасных целых чисел и привела бы к потере точности ещё до того, как BigInt его увидит.

Ловушка: никогда не используйте new с обёртками примитивов

JavaScript позволяет создать объект-обёртку вручную с помощью new Number(1), new String("x") или new Boolean(false) — но почти никогда не стоит этого делать. Обёртка, созданная с new, является настоящим object, а каждый object является истинным (truthy), включая тот, что оборачивает false:

javascript— editable

Это классический источник ошибок. Вызов конструктора без new — совершенно нормален и полезен: Number("42"), String(123) и Boolean(value) выполняют обычное преобразование типов и возвращают примитивы, а не объекты.

Итоги

  • Примитивы — это простые, неизменяемые значения, хранящиеся по значению; объекты — изменяемые и хранятся по ссылке.
  • Вызов метода на примитиве работает потому, что JavaScript оборачивает его во временный object, выполняет метод, а затем уничтожает обёртку.
  • String, Number, Boolean, Symbol и BigInt предоставляют методы; null и undefined не имеют обёртки и выбрасывают ошибку при обращении к свойству.
  • Используйте функции-обёртки без new для преобразования типов. Никогда не используйте new для создания объектов-обёрток в обычном коде — они всегда истинны и ведут себя неожиданно.

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

Практика

Практика
Какие из следующих методов применимы к примитивным типам данных в JavaScript?
Какие из следующих методов применимы к примитивным типам данных в JavaScript?
Was this page helpful?