В рубрике Essentials мы рассматриваем наиболее используемые и важные методы. Эта рубрика будет полезна разработчикам, которые уже знают другой язык или тем, кто хочет быстро вникнуть в тему. В этой статье мы поговорим о типах и структурах данных.
Здесь, я не буду углубляться в детали, вместо этого мы пробежимся по списку основных тем, с которыми вы со временем столкнётесь в JS. Я дам список ресурсов для обучения. Другими словами, лучше разобраться с этим сейчас, чем откладывать на потом.
Уровень подготовки
Для этой темы особой подготовки не нужно. Это основы любого языка, но в JavaScript всё немного запутанно.
Типы и структуры данных. Основы.
Далее мы будем использовать оператор typeof,
чтобы разобраться с типами.
Есть ли типы в JS?
Кто-то может сказать, что JS не типизированный язык или что его типы нельзя назвать системными типами. От вас не требуется объявлять тип при создании переменной, как в других строго типизированных языках, например int x = 10.
Я же (как и JS специалисты) заявляю, что в JS есть типы.
JS можно назвать и динамически типизированным и слабо типизированным.
Статическая типизация
JS не является статически типизированным языком, если только вы не используете такие инструменты как Typescript или Flow, которые компилируют в JS код. Мы коснёмся этой темы для примера.
Статическая типизация подразумевает принудительное присвоение типа, который не так просто изменить. Все переменные должны объявляться с типом.
int x = 5 string y = 'abc'
Динамическая типизация
Языки с динамической типизацией допускают изменение типа во время рабочего цикла. Это значит, что запустив выполнение кода, компилятор/интерпретатор, увидев переменную и её значение, сам определит тип данных. В этом случае, тип также принудительно задан, просто JS сам определяет его.
var a = 1 // int b = 'test' // string // etc
Слабая типизация
Слабо типизированные языки допускают изменение типа. Например: 1 + '2' // '12'
. JS видит, что вы пытаетесь сложить число и строку (недопустимая операция), в результате он преобразует число в строку и возвращает ‘12’.
Примитивы
Эти шесть типов задуманы как примитивы. Они не являются объектами и не имеют собственных методов. Все примитивы неизменны.
- Boolean — true or false
- Null — нет значения
- Undefined — объявленная переменная, но без значения
- Number — целочисленные, с плавающей точкой и т.д.
- String —строка
- Symbol — уникальное значение, которое не совпадает с другими
Всё остальное это объекты.
Объекты
Приведу несколько стандартных объектов. Обратите внимание, некоторые из них были в списке примитивов, не спутайте их. Эти ведут себя как конструкторы, например Boolean('a') // true .
Два из них являются основными, с их помощью вы будете создавать свои собственные структуры:
Есть ещё множество объектов, вот некоторые из них:
- Function
- Boolean
- Symbol
- Error
- Number
- String
- RegExp
- Math
- Set
Так, где же здесь подвох?
Неразбериха начинается, когда отличающиеся типы смешиваются. JavaScript преобразует типы на своё усмотрение.
Далее, я расскажу о других непонятных моментах и хитростях.
Важные принципы
- Все значения примитивов ― неизменны
- Осторожно с приведением типов
- Здесь нет места статической типизации т.е.
int num = 5
- Движок JavaScript сам определяет типы
Странности
В JavaScript много странностей. Подробней здесь: Wtf JS?
Почему Null это объект?
Документация причисляет Null к примитивам, тем не менее оператор typeof
возвращает значение ‘object’
.
По сути, это баг, который не исправили, потому что существующий код перестанет работать. Этот баг присутствовал ещё с первой версии JavaScript, он пришёл из функции typeof
в исходниках JS. Я покажу это с помощью псевдокода:
Улавливаете? Они не проверили null
…
Подробней о причинах отказа исправлять баг, читайте здесь. А здесь, та часть исходника JS о которой я говорил.
Почему не number стало number?
typeof NaN // 'number' WTF!?
Если коротко, то NaN
определён как числовой тип, но это не настоящее число. NaN
― это результат неких математических операций, который не может считаться числом.
Или ещё короче, потому что эксперты так сказали 🙂
Примитив не является объектом и не имеет собственных методов
Если примитивы не имеют методов, тогда почему работает 'abc'.length
?
Я не ошибся, так сказано в документации.
Примитивы — это данные (значения, типы данных), которые не являются объектами и не имеют методов. В JavaScript есть 6 примитивов: string, number, boolean, null, undefined, symbol (новые из ECMAScript 2015).
Во-первых, не путайте конструкторы и примитивы. Каждый примитив имеет конструктор или родительский объект. JS понимает, когда вы пытаетесь применить метод к примитиву и самостоятельно использует конструктор, чтобы создать объект из вашего примитива. После того как метод запущен, этот объект удаляется из памяти.
Вот пример:
По факту, строки являются примитивами, как упоминалось в статье, а не полноценными объектами. JS понимает, когда вы пытаетесь применить метод на объект String
и преобразует ваш примитив в строковый объект. Когда дело сделано, временный объект удаляется и всё становится на свои места.
Tips and Tricks
Способы использовать типы в своих интересах.
Пользуйтесь этим с осторожностью. В большинстве случаев, используйте Number(str)
parseInt(x)
String(num)
и т.д. Это на всякий случай, если вдруг встретите подобное в чужом коде, чтобы знать зачем этот код. Или если вы играете в Code golf ⛳️
Перевод статьи CodeDraken : JavaScript Essentials: Types & Data Structures