Типы данных
Значение в JavaScript всегда относится к данным определённого типа. Например, это может быть строка или число.
Есть восемь основных типов данных в JavaScript. В этой главе мы рассмотрим их в общем, а в следующих главах поговорим подробнее о каждом.
Переменная в JavaScript может содержать любые данные. В один момент там может быть строка, а в другой – число:
// Не будет ошибкой let message = "hello"; message = 123456;
Языки программирования, в которых такое возможно, называются «динамически типизированными». Это значит, что типы данных есть, но переменные не привязаны ни к одному из них.
Число
let n = 123; n = 12.345;
Числовой тип данных ( number ) представляет как целочисленные значения, так и числа с плавающей точкой.
Существует множество операций для чисел, например, умножение * , деление / , сложение + , вычитание — и так далее.
Кроме обычных чисел, существуют так называемые «специальные числовые значения», которые относятся к этому типу данных: Infinity , -Infinity и NaN .
-
Infinity представляет собой математическую бесконечность ∞. Это особое значение, которое больше любого числа. Мы можем получить его в результате деления на ноль:
alert( 1 / 0 ); // Infinity
Или задать его явно:
alert( Infinity ); // Infinity
alert( "не число" / 2 ); // NaN, такое деление является ошибкой
Значение NaN «прилипчиво». Любая математическая операция с NaN возвращает NaN :
alert( NaN + 1 ); // NaN alert( 3 * NaN ); // NaN alert( "не число" / 2 - 1 ); // NaN
Математические операции – безопасны
Математические операции в JavaScript «безопасны». Мы можем делать что угодно: делить на ноль, обращаться с нечисловыми строками как с числами и т.д.
Скрипт никогда не остановится с фатальной ошибкой (не «умрёт»). В худшем случае мы получим NaN как результат выполнения.
Специальные числовые значения относятся к типу «число». Конечно, это не числа в привычном значении этого слова.
Подробнее о работе с числами мы поговорим в главе Числа.
BigInt
В JavaScript тип number не может безопасно работать с числами, большими, чем (2 53 -1) (т. е. 9007199254740991 ) или меньшими, чем -(2 53 -1) для отрицательных чисел.
Если говорить совсем точно, то, технически, тип number может хранить большие целые числа (до 1.7976931348623157 * 10 308 ), но за пределами безопасного диапазона целых чисел ±(2 53 -1) будет ошибка точности, так как не все цифры помещаются в фиксированную 64-битную память. Поэтому можно хранить «приблизительное» значение.
Например, эти два числа (прямо за пределами безопасного диапазона) совпадают:
console.log(9007199254740991 + 1); // 9007199254740992 console.log(9007199254740991 + 2); // 9007199254740992
То есть все нечетные целые числа, большие чем (2 53 -1) , вообще не могут храниться в типе number .
В большинстве случаев безопасного диапазона чисел от -(2 53 -1) до (2 53 -1) вполне достаточно, но иногда нам требуется весь диапазон действительно гигантских целых чисел без каких-либо ограничений или пропущенных значений внутри него. Например, в криптографии или при использовании метки времени («timestamp») с микросекундами.
Тип BigInt был добавлен в JavaScript, чтобы дать возможность работать с целыми числами произвольной длины.
Чтобы создать значение типа BigInt , необходимо добавить n в конец числового литерала:
// символ "n" в конце означает, что это BigInt const bigInt = 1234567890123456789012345678901234567890n;
Так как необходимость в использовании BigInt –чисел появляется достаточно редко, мы рассмотрим их в отдельной главе BigInt. Ознакомьтесь с ней, когда вам понадобятся настолько большие числа.
В данный момент BigInt поддерживается только в браузерах Firefox, Chrome, Edge и Safari, но не поддерживается в IE.
Строка
Строка ( string ) в JavaScript должна быть заключена в кавычки.
let str = "Привет"; let str2 = 'Одинарные кавычки тоже подойдут'; let phrase = `Обратные кавычки позволяют встраивать переменные $`;
В JavaScript существует три типа кавычек.
- Двойные кавычки: «Привет» .
- Одинарные кавычки: ‘Привет’ .
- Обратные кавычки: `Привет` .
Двойные или одинарные кавычки являются «простыми», между ними нет разницы в JavaScript.
Обратные же кавычки имеют расширенную функциональность. Они позволяют нам встраивать выражения в строку, заключая их в $ . Например:
let name = "Иван"; // Вставим переменную alert( `Привет, $!` ); // Привет, Иван! // Вставим выражение alert( `результат: $` ); // результат: 3
Выражение внутри $ вычисляется, и его результат становится частью строки. Мы можем положить туда всё, что угодно: переменную name , или выражение 1 + 2 , или что-то более сложное.
Обратите внимание, что это можно делать только в обратных кавычках. Другие кавычки не имеют такой функциональности встраивания!
alert( "результат: $" ); // результат: $ (двойные кавычки ничего не делают)
Мы рассмотрим строки более подробно в главе Строки.
Нет отдельного типа данных для одного символа.
В некоторых языках, например C и Java, для хранения одного символа, например «a» или «%» , существует отдельный тип. В языках C и Java это char .
В JavaScript подобного типа нет, есть только тип string . Строка может содержать ноль символов (быть пустой), один символ или множество.
Булевый (логический) тип
Булевый тип ( boolean ) может принимать только два значения: true (истина) и false (ложь).
Такой тип, как правило, используется для хранения значений да/нет: true значит «да, правильно», а false значит «нет, не правильно».
let nameFieldChecked = true; // да, поле отмечено let ageFieldChecked = false; // нет, поле не отмечено
Булевые значения также могут быть результатом сравнений:
let isGreater = 4 > 1; alert( isGreater ); // true (результатом сравнения будет "да")
Мы рассмотрим булевые значения более подробно в главе Логические операторы.
Значение «null»
Специальное значение null не относится ни к одному из типов, описанных выше.
Оно формирует отдельный тип, который содержит только значение null :
let age = null;
В JavaScript null не является «ссылкой на несуществующий объект» или «нулевым указателем», как в некоторых других языках.
Это просто специальное значение, которое представляет собой «ничего», «пусто» или «значение неизвестно».
В приведённом выше коде указано, что значение переменной age неизвестно.
Значение «undefined»
Специальное значение undefined также стоит особняком. Оно формирует тип из самого себя так же, как и null .
Оно означает, что «значение не было присвоено».
Если переменная объявлена, но ей не присвоено никакого значения, то её значением будет undefined :
let age; alert(age); // выведет "undefined"
Технически мы можем присвоить значение undefined любой переменной:
let age = 123; // изменяем значение на undefined age = undefined; alert(age); // "undefined"
…Но так делать не рекомендуется. Обычно null используется для присвоения переменной «пустого» или «неизвестного» значения, а undefined – для проверок, была ли переменная назначена.
Объекты и символы
Тип object (объект) – особенный.
Все остальные типы называются «примитивными», потому что их значениями могут быть только простые значения (будь то строка, или число, или что-то ещё). В объектах же хранят коллекции данных или более сложные структуры.
Объекты занимают важное место в языке и требуют особого внимания. Мы разберёмся с ними в главе Объекты после того, как узнаем больше о примитивах.
Тип symbol (символ) используется для создания уникальных идентификаторов в объектах. Мы упоминаем здесь о нём для полноты картины, изучим этот тип после объектов.
Оператор typeof
Оператор typeof возвращает тип аргумента. Это полезно, когда мы хотим обрабатывать значения различных типов по-разному или просто хотим сделать проверку.
У него есть две синтаксические формы:
// Обычный синтаксис typeof 5 // Выведет "number" // Синтаксис, напоминающий вызов функции (встречается реже) typeof(5) // Также выведет "number"
Если передается выражение, то нужно заключать его в скобки, т.к. typeof имеет более высокий приоритет, чем бинарные операторы:
typeof 50 + " Квартир"; // Выведет "number Квартир" typeof (50 + " Квартир"); // Выведет "string"
Другими словами, скобки необходимы для определения типа значения, которое получилось в результате выполнения выражения в них.
Вызов typeof x возвращает строку с именем типа:
typeof undefined // "undefined" typeof 0 // "number" typeof 10n // "bigint" typeof true // "boolean" typeof "foo" // "string" typeof Symbol("id") // "symbol" typeof Math // "object" (1) typeof null // "object" (2) typeof alert // "function" (3)
Последние три строки нуждаются в пояснении:
- Math — это встроенный объект, который предоставляет математические операции и константы. Мы рассмотрим его подробнее в главе Числа. Здесь он служит лишь примером объекта.
- Результатом вызова typeof null является «object» . Это официально признанная ошибка в typeof , ведущая начало с времён создания JavaScript и сохранённая для совместимости. Конечно, null не является объектом. Это специальное значение с отдельным типом.
- Вызов typeof alert возвращает «function» , потому что alert является функцией. Мы изучим функции в следующих главах, где заодно увидим, что в JavaScript нет специального типа «функция». Функции относятся к объектному типу. Но typeof обрабатывает их особым образом, возвращая «function» . Так тоже повелось от создания JavaScript. Формально это неверно, но может быть удобным на практике.
Итого
В JavaScript есть 8 основных типов данных.
- Семь из них называют «примитивными» типами данных:
- number для любых чисел: целочисленных или чисел с плавающей точкой; целочисленные значения ограничены диапазоном ±(2 53 -1) .
- bigint для целых чисел произвольной длины.
- string для строк. Строка может содержать ноль или больше символов, нет отдельного символьного типа.
- boolean для true / false .
- null для неизвестных значений – отдельный тип, имеющий одно значение null .
- undefined для неприсвоенных значений – отдельный тип, имеющий одно значение undefined .
- symbol для уникальных идентификаторов.
- object для более сложных структур данных.
Оператор typeof позволяет нам увидеть, какой тип данных сохранён в переменной.
- Имеет две формы: typeof x или typeof(x) .
- Возвращает строку с именем типа. Например, «string» .
- Для null возвращается «object» – это ошибка в языке, на самом деле это не объект.
В следующих главах мы сконцентрируемся на примитивных значениях, а когда познакомимся с ними, перейдём к объектам.
Сколько всего типов данных в javascript
Все используемые данные в javascript имеют определенный тип. В JavaScript имеется восемь типов данных:
- String : представляет строку
- Number : представляет числовое значение
- BigInt : предназначен для представления очень больших целых чисел
- Boolean : представляет логическое значение true или false
- Undefined : представляет одно специальное значение — undefined и указывает, что значение не установлено
- Null : представляет одно специальное значение — null и указывает на отсутствие значения
- Symbol : представляет уникальное значение, которое часто применяется для обращения к свойствам сложных объектов
- Object : представляет комплексный объект
Первые семь типов представляют примитивные типы данных. Последний тип — Object представляет сложный, комплексный тип данных, который состоит из значений примитивных типов или других объектов. Рассмотрим основные примитивные типы данных.
Числовые данные
Number
Тип Number представляет числа в JavaScript, которые могут быть целыми или дробными:
- Целые числа, например, 35. Мы можем использовать как положительные, так и отрицательные числа. Диапазон используемых чисел: от -2 53 до 2 53
- Дробные числа (числа с плавающей точкой). В качестве разделителя дробной и целой части применяется точка, например, 3.5575 . Опять же можно использовать как положительные, так и отрицательные числа. Для чисел с плавающей точкой используется тот же диапазон: от -2 53 до 2 53
const x = 45; const y = 123.897; const z = -0.123;
JavaScript поддерживает возможность определять числа в двоичной, восьмеричной и шестнадцатеричной системах, что очень удобно, если нам предстоить проводить поразрядные операции с отдельными битами числа. Для определения числа в двоичной системе, перед числом указывается префикс 0b :
const num1 = 0b1011; // число 11 в десятичной системе console.log(num1); // 11
В данном случае константа num1 равна 0b1011 , что в десятичной системе эквивалентно 11.
Для определения числа в восьмеричной системе, перед числом указывается префикс 0o :
const num1 = 0o11; // число 9 в десятичной системе console.log(num1); // 9
Для определения числа в шестнадцатеричной системе, перед числом указывается префикс 0x :
const num1 = 0xff; // число 255 в десятичной системе console.log(num1); // 255 const num2 = 0x1A; // число 26 в десятичной системе console.log(num2); // 26
Начиная со стандарта ECMA2021 в JavaScript для увеличения читабельности в качестве разделителя между разрядами можно использовать символ подчеркивания _:
const num1 = 1234567; const num2 = 123_4567; // число равное num1 const num3 = 1234567890; const num4 = 12_3456_7890; // число равное num3
Тип BigInt
Тип BigInt добавлен в последних стандартах JavaScript для представления очень больших целых чисел, которые выходят за пределы диапазона типа number. Это не значит, что мы не можем совсем работать с большими числами с помощью типа number, но работа с ними в случае с типом number будет сопряжена с проблемами. Рассмотрим небольшой пример:
let num = 9007199254740991 console.log(num); // 9007199254740991 console.log(num + 1); // 9007199254740992 console.log(num + 2); // 9007199254740992
Здесь переменной num присваивается максимальное значение. И далее прибавляем к ней некоторые значения и выводим на консоль результат. И результаты могут нас смутить, особенно в случае прибавления числа 2.
Стоит отметить, что тип Number ограничен, хотя и позволяет оперировать довольно большим диапазоном чисел. В частности, мы можем использовать специальные константы Number.MIN_VALUE и Number.MAX_VALUE для проверки минимального и максимального возможных значений для типа Number:
console.log(Number.MIN_VALUE); // 5e-324 console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
Например, рассмотрим следующий пример:
const num = 9223372036854775801; console.log(num); // 9223372036854776000
В силу ограничений типа Number на консоли мы увидим несколько другое число, нежели мы присвоили константе num. Это может негативно влиять на точность в вычислениях. И для подобных подобных чисел как раз предназначен тип BigInt . Для определения числа как значения типа BigInt в конце числа добавляется суффикс n :
let dimension = 19007n; const value = 2545n;
Например, изменим из предыдущего примера тип number на bigint:
const num = 9223372036854775801n; console.log(num); // 9223372036854775801n
Теперь консоль выводит корректный результат.
Тип Boolean
Тип Boolean представляет булевые или логические значения true (верно) и false (ложно):
const isAlive = true; const isDead = false;
Строки String
Тип String представляет строки. Для определения строк применяются кавычки, причем, можно использовать как двойные, так одинарные, так и косые кавычки. Единственно ограничение: тип закрывающей кавычки должен быть тот же, что и тип открывающей, то есть либо обе двойные, либо обе одинарные.
const user = "Tom"; const company = 'Microsoft'; const language = `JavaScript`; console.log(user); console.log(company); console.log(language);
Если внутри строки встречаются кавычки, то мы их должны экранировать слешем. Например, пусть у нас есть текст «Бюро «Рога и копыта»» . Теперь экранируем кавычки:
const company = "Бюро \"Рога и копыта\"";
Также мы можем внутри стоки использовать другой тип кавычек:
constcompany1 = "Бюро 'Рога и копыта'"; const company2 = 'Бюро "Рога и копыта"';
Также строка может содержать специальные символы — управляющие последовательности, которые интерпретируются определенным образом. Самые распространенные последовательности — это «\n» (перевод на другую строку) и «\t» (табуляция). Например:
const text = "Hello METANIT.COM\nHello\tWorld"; console.log(text);
При выводе на консоль текст из константы text будет интерпретироваться следующим образом:
Hello METANIT.COM Hello World
Интерполяция
Использование косых кавычек позволяет нам применять такой прием как интерполяция — встраивать данные в строку. Например:
const user = "Tom"; const text = `Name: $`; console.log(text); // Name: Tom
Для встраивания значений выражений (например, значений других переменных и констант) в строку перед выражением ставится знак доллара $ , после которого в фигурных скобках указывается выражение. Так, в примере выше $ означает, что в этом месте строки надо встроить значение переменной user .
Подобным образом можно встраивать и больше количество данных:
const user = "Tom"; const age = 37; const isMarried = false; const text = `Name: $ Age: $ IsMarried: $`; console.log(text); // Name: Tom Age: 37 IsMarried: false
Кроме интерполяции косые кавычки позволяют определять многострочный текст:
const text = `Мы все учились понемногу Чему-нибудь и как-нибудь, Так воспитаньем, слава богу, У нас немудрено блеснуть.`; console.log(text);
Консольный вывод браузера:
Мы все учились понемногу Чему-нибудь и как-нибудь, Так воспитаньем, слава богу, У нас немудрено блеснуть.
null и undefined
undefined указывает, что значение не определено или не установлено. Например, когда мы только определяем переменную без присвоения ей начального значения, она представляет тип undefined:
let email; console.log(email); // выведет undefined
Присвоение значение null означает, что у переменной отсутствует значение:
let email; console.log(email); // undefined email = null; console.log(email); // null
Стоит отметить, что хотя в принципе можно переменной присвоить значение undefined , как в следующем случае:
let email = "tome@mimimail.com"; email = undefined; // установим тип undefined console.log(email); // undefined
Но основной смысл undefined состоит в том, что переменная неинициализирована, что обычно происходит до первого присвоения ей какого-либо значения. Поэтому обычно не предполагается, что переменной явным образом будет присваиваться значение undefined . В тоже время этот тип может быть полезен — мы можем использовать его на проверку инициализации переменной. Но если же нам надо указать, что у переменной нет никакого значения, то ей присваивается null , а не undefine .
object
Тип object представляет сложный объект. Простейшее определение объекта представляют фигурные скобки:
const user = <>;
Объект может иметь различные свойства и методы:
const user = ; console.log(user.name);
В данном случае объект называется user, и он имеет два свойства: name и age, которые в качестве значения принимают данные других типов. Это краткое описание объектов, более подробно объекты мы рассморим в последующих статьях.
Слабая/динамическая типизация
JavaScript является языком со слабой и динамической типизацией. Это значит, что переменные могут динамически менять тип. Например:
let id; // тип undefined console.log(id); id = 45; // тип number console.log(id); id = "45"; // тип string console.log(id);
Несмотря на то, что во втором и третьем случае консоль выведет нам число 45, но во втором случае переменная id будет представлять число, а в третьем случае — строку.
Оператор typeof
С помощью оператора typeof можно получить тип переменной, что может быть полезно, когда в зависимости от типа переменной необходимо выполнить те или иные действия:
let id; console.log(typeof id); // undefined id = 45; console.log(typeof id); // number id = 45n; console.log(typeof id); // bigint id = "45"; console.log(typeof id); // string
Стоит отметить, что для значения null оператор typeof возвращает значение «object», несмотря на то, что согласно спецификации JavaScript значение null представляет отдельный тип.
Типы данных в JavaScript. Инструкция для начинающих
Как и любая компьютерная программа, JavaScript нуждается в наведении порядка в данных, в их структурировании. На языке JavaScript мы говорим, что если данные имеют одинаковую структуру, то они имеют одинаковый тип. Внутренняя организация данных может быть простой, как ДА или НЕТ, а может быть весьма замысловатой, как дерево HTML-элементов или маршруты на карте навигатора.
Примитивные типы. JavaScript предлагает разработчику несколько простых, примитивных, типов. Среди них: boolean , number , string . Примитивными эти типы называют за то, что значения этих типов нельзя поменять. Их можно клонировать, встроить в другие значения. Через минуту увидим как это происходит
Работа с наборами. Дополнительно JavaScript предлагает несколько типов объектов для работы с наборами — массивы, словари, множества. Это очень кстати, попробуй вспомни, как эффективно реализовать сортировку.
Готовые структуры для хранения информации на все случаи жизни не напасешься, поэтому JavaScript предоставляет разработчику полную свободу в этих вопросах, и разработчик может создавать самостоятельно бесконечное разнообразие типов для собственных нужд.
Давайте обсудим детали разных типов данных, как примитивных, так и встроенных. Поговорим и о кастомных типах.
Примитивные типы
JavaScript различает семь типов:
undefined — обозначает тип значения переменной, которую объявили, но не инициализировали. Этот тип для данных, которых нет.
boolean — принимает только два значения «истина» и «ложь».
number — попытка научиться записывать любое число в ограниченную память компьютера (провалилась).
string — последовательность символов. JavaScript умеет преобразовывать значение любого примитивного типа в строку. Значение типа string в JavaScript неизменяемое, нельзя изменить одну букву в слове.
symbol — специальный тип данных. Задача значений типа symbol — служить специальными именами для обозначения специальных свойств объектов. Так много слов «специально», что мы дадим разъяснения ниже.
bigint — низкий поклон в сторону крипро- валют, токенов, контрактов. Они оперируют большими числами, и там этот тип данных очень пригождается. Скорее всего, не пригодится в вашем обычном фронтенде.
object — кроме примитивных типов в JavaScript есть структурные типы (объекты), а среди объектов особо выделяют функции. Обратите внимание, что в JavaScript функции это тоже объекты.
А как же null ? null — ещё одна возможность обозначить данные, которых нет. Да, в JavaScript есть целых два способа для обозначения ситуации, когда в переменной нет значения. Обратите внимание, что в JavaScript null это значение, а не тип данных и это значение может содержаться в JSON, а undefined в JSON не бывает.
Тип undefined
Когда вы объявляете переменную, но не присваиваете ей значение, переменная получает значение «по умолчанию» и это значение undefined , которое имеет тип undefined.
let buffer;Переменная buffer объявлена с ключевым словом let , но до тех пока она не получила явного значения ее значение undefined .
Хитрость JavaScript в том, что иногда разработчик присваивает переменной результат работы функции, но переменная все равно остается undefined . В следующем примере buffer получает значение при объявлении. Можете ли вы догадаться почему buffer всё равно undefined ?
function trickyComputation () < let a = 0; while(a<3)< a+=2; >> let buffer = trickyComputation();Все дело в том, что trickyComputation не возвращает значения. Попробуйте рассуждать о том, что цель функции — «присвоить значение» ключевому слову return . В вышеприведенном примере нет return , и этот самый воображаемый return остается неинициализированным, отсюда и undefined .
Будьте внимательны к функциям.
Тип boolean
В JavaScript про любое значение можно задать вопрос «похоже ли оно на правду?». Значение true — правда, false — ложь. Пустое значение обычно значит false.
Посмотрим на практике. Для проверки правдивости будем пользоваться вот таким методом showTrueness .
const showTrueness = (n,value)=> console.log(`$ - $`);// эти значения похожи на ложь showTrueness(1,false); // false showTrueness(2,''); // false showTrueness(3,0) // falseКогда значение отличается от банально-начального, оно обычно истинно.
showTrueness(1, true); // true showTrueness(2, 42); // true showTrueness(3, 'false') // trueКак видите, слово false получает приговор — истина! Но это еще не самый курьёзный случай с boolean :
showTrueness(1, []); // true showTrueness(2, <>); // true showTrueness(3, [] === []); // false showTrueness(4, <> === <>); // falseХотя обычно пустые значения это ложь, пустой массив (1) и пустой объект (2) оказались истиной. А ещё в следующем отрывке JavaScript рассматривает число 0 эквивалентной строке ‘0’.
Видите 0==’0′ показывает true . При этом по отдельности число 0 и строка ‘0’ относятся к разным типам.
showTrueness(1, 0 == '0'); // true showTrueness(2, 0); // false showTrueness(3, '0'); // trueЭто происходит из-за способности JavaScript преобразовывать значения из одного типа в другой. Если невнимательно следить за такими преобразованиями, могут возникнуть ошибки, которые очень тяжело найти.
Для избежания сюрпризов используйте явное преобразования значений между типами и строгое сравнение (===) (! ==). В этом вам поможет набор правил eslinter от академии.
Тип number
Тип значения number предназначен для моделирования действительных чисел. Действительных чисел очень много — бесконечно много — а компьютерная память ограничена. Инженерам из IEEE пришлось даже выпустить отдельный международный стандарт для чисел с плавающей точкой — IEEE 754.
Во многих случаях числа с плавающей точкой ведут себя нормально. Сумма чисел 1 и 2 равна 3, а сумма чисел 0.1 и 0.2 равна сумме чисел 0.2 и 0.1. Но это не всегда так, и 0.1 + 0.2 может быть не равно 0.3. Если в школе вам говорили, что от перемены мест сумма не меняется, то в JavaScript это не всегда верно.
И если будете делать выписку в крипто-банке, два раза подумайте, в каком порядке вы хотите складывать числа. Потому что значение переменной currentBalanceV1 больше значения переменной currentBalanceV2 , а всё потому что величины складываемых чисел сильно отличаются.
showTrueness(1, 1+2 === 3); // true const lastMonthCredits = Array.from (,()=>Number.EPSILON/10); const previousMonthBalance = 0.8; const currentBalanceV1 = previousMonthBalance + lastMonthCredits.reduce((a,b)=>a+b,0); const currentBalanceV2 = 0 + lastMonthCredits.reduce((a,b)=>a+b,previousMonthBalance); showTrueness(2, currentBalanceV1>currentBalanceV2); // true showTrueness(3, 0.1+0.2 === 0.2+0.1) // trueСоветы при работе с числами
- При работе с числами старайтесь сначала делать действия над числами сравнимой величины
- При работе с числами старайтесь сравнивать их порядок, (что больше, а что меньше), а не равенство.
- Изучите назначение предопределенных констант Number.MAX_SAFE_INTEGER , Number.EPSILON и других.
Задание для самопроверки. На сколько отличаются currentBalanceV1 , currentBalanceV2 и previousMonthBalance ?
Тип string
Строки в JavaScript — это неизменяемые цепочки букв. Вы можете добавлять строки одну к другой, брать нужную букву по порядку. Нумерация букв в строке начинается с нуля, поэтому вы видите в примере (-1).
const show = (value)=>console.log(value); const alfavit = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя'; show(alfavit); // "абвгдеёжзийклмнопрстуфхцчшщъыьэюя" show(alfavit[1-1]); // "а" show(alfavit[33-1]); //"я"Поскольку строка неизменяемая, вы не можете просто взять и поменять букву, забить звездочками часть номера банковской карты не получится.
alfavit[2-1]='*'; show(alfavit); // "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"В виде строк можно хранить любой вид данных, нужно только договориться. Однако мы не рекомендуем вам изобретать велосипед. Лучше используйте общепринятые способы преобразования данных в строку и обратно: JSON.stringify , JSON.parse (для превращения в JSON и обратно), Intl.NumberFormat , Intl.DateFormat .
Оператор typeof
Вы можете использовать оператор typeof для определения типа значения. Этот оператор воздействует на переменную и возвращает имя типа (если знает)
const show = (value, type)=>console.log(`typeof ($) is $`); const whatIsMyTypeName = (value)=> < switch(typeof value)< case 'boolean': case 'number': case 'string': return show(value, typeof value); default: show(value, 'выясним позднее') >> whatIsMyTypeName(true); // typeof (true) is boolean" whatIsMyTypeName(42); // "typeof (42) is number" whatIsMyTypeName('миру-мир!'); // "typeof (миру-мир!) is string" whatIsMyTypeName(<>); // "typeof ([object Object]) is выясним позднее" whatIsMyTypeName(window); // "typeof ([object Window]) is выясним позднее"Встроенные типы
В JavaScript вам доступно много типов данных — ими могут быть элементы браузера, документа, видео и изображения и многое другое. Полный набор зависит от окружения. Но почти наверняка вам будут доступны массивы, словари и множества.
Array (массивы)
Сразу обратите внимание, что слово Array мы употребляем с большой буквы, в то время как boolean , number , string — с маленькой.
Если вы разработчик на JavaScript, то методы работы с массивами нужно знать и уметь вспомнить, даже если вас разбудили посреди ночи. Проверьте, что вы знаете о существовании методов массива length, from, map, sort, reduce, filter, find, indexOf, findIndex
Вы можете получить значение из массива по индексу, а можете заменить это значение другим. Индексом значения в массиве выступает число. Индексы идут от 0 в сторону увеличения.
JavaScript не будет следить за тем, обращаетесь ли вы по индексу правомерно или выходите за пределы массива. Вы даже можете положить новое значение по индексу «минус один» и получить его обратно. Однако вас ждут сюрпризы, если вы не будете контролировать размеры массива и значения индекса.
const show = (index, value)=> console.log(`$: $`); const items = [ 'Chrome', 'Opera', 'Edge' ]; // Предоставляет элемент show(1,items[1]) // "1: Opera" // Ошибки нет, но и элемента тоже show(100, items[100]); "100: undefined" // Как, впрочем, и здесь show(-1, items[-1]);// "-1: undefined" items[12] = 'safari'; items[-1] = 'IE'; // Ошибки нет, а элемент появился show(12, items[12]);//"12: safari" show(-1, items[-1]);// "-1: IE" // а где IE? show('all', items)"all: Chrome,Opera,Edge. safari" // А тут всё ещё есть show(-1, items[-1]);// "-1: IE"Совет: контролируйте индексы, знайте размер массивов, с которыми работаете.
Set
Тип данных Set позволяет вам хранить набор уникальных элементов. Этим он отличается от массива. При работе с массивом вам придется предпринимать специальные усилия для поддержания уникальности элементов, Set сделает это за вас. В отличии от массива Set не позволяет произвольный доступ к элементу. Вы можете проверить наличие и получить список в порядке вставки.
const items = new Set(Array.from (,(_,ix)=>ix)); const str = (value)=>`$`; const compare = (left,right)=>leftcompare(left,right); const byStringValue =(left,right)=>compare(str(left),str(right)); console.log([. items].sort(byNumbericalValue)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] console.log([. items].sort(byStringValue)); // [0, 1, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9] items.add(100); items.add(20); //порядок, в котором JavaScript отдает содержимое Set, зависит от порядка добавления элементов console.log([. items].sort(byNumbericalValue)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 20, 100] console.log([. items].sort(byStringValue)); // [0, 1, 10, 100, 11, 2, 20, 3, 4, 5, 6, 7, 8, 9] console.log([. items]); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 100, 20]Совет: для вывода элементов из Set в нужном порядке позаботьтесь о функции сортировки.
Кастомные объекты <> — ассоциативный массив
JavaScript объекты — это словари, где строковому ключу поставлен в соответствие элемент-значение. Возможны два синтаксиса доступа к значению ключа
const dictionary = < 'language':'javascript', 'type': 'structured', 'age': 25 >console.log(dictionary.language); // javascript console.log(dictionary['language']); // javascript const key = 'language'; console.log(dictionary[key]); // javascriptВажно! Ключ в кастомных объектах — это строковое значение. JavaScript неявно преобразует значение к строковому типу перед использованием его в качестве ключа.
Это ограничение не позволяет использовать объекты для создания связей между HTML-элементами и дополнительными данным, нужными для работы программы. Для этого используйте тип Map .
Map
По логическому устройству Map очень похож на ассоциативный массив, но свободен от ограничения на вид ключа.
const DictionaryCO = <>; // инициализируем вариант ассоциативного массива на основе обычного объекта const DictionaryMap = new Map(); // инициализируем вариант ассоциативного массива на основе встроенного типа Map // Первый эксперимент будет связывать ключ 'k1' и значение 'v1' const aKey = 'k1'; const aValue = 'v1'; // Второй эксперимент будет связывать ключ в виде объекта и значение - строку // такой вариант в жизни встречается если для нескольких HTML элементов нужно ввести дополнительные данные, которые нельзя положить в data-xxx атрибут const bKey = ; const bValue = 'v2'; // Третий эксперимент покажет нам недостатки ассоциативного массива на основе обычного объекта. Мы используем в качестве ключа - другой объект const cKey = ; const cValue = 'v3'; // заполняем первый ассоциативный массив (который в виде объекта) DictionaryCO[aKey] = aValue; DictionaryCO[bKey] = bValue; DictionaryCO[cKey] = cValue; // заполняем второй ассоциативный массива (которы в виде Map) DictionaryMap.set(aKey, aValue); DictionaryMap.set(bKey, bValue); DictionaryMap.set(cKey, cValue); console.log('a object', DictionaryCO[aKey]); // "a object", "v1" console.log('b object', DictionaryCO[bKey]); // "b object", "v2" // хотя мы пытаемся получить значение по ключу cKey, почему-то // мы получаем значение, которое связали с ключом bKey console.log('c object, oops!', DictionaryCO[cKey]); // "c object, oops!", "v2" console.log('a map', DictionaryMap.get(aKey)); // "a map", "v1" console.log('b map', DictionaryMap.get(bKey)); // "b map", "v2" // в этом варианте ассоциативного массива все сработало так, как мы и ожидали console.log('c map', DictionaryMap.get(cKey)); // "c map", "v3"Собственные структуры данных
Утиная типизация
Программисты работают с лозунгом «Algorithms + Data Structures = Programs». При работе с JavaScript разработчик преобразует требования заказчика в алгоритмы и структуры данных. Примитивных типов данных, доступных в JavaScript явно недостаточно для всего разнообразия бизнес задач, поэтому приходится использовать кастомные структуры. Для приложения электронной очереди потребуется структура с номером и временем, для умного дома — структура с данными о температуре чайника, заполненности холодильника и т. п.
let cusomerInQueue = < numberOnScreen: 'A42', timeTaken: '11:40' >let smartHouseState = < kettler: 80, fridge:< milk: true, banana: false, >, >В вашей программе вы получаете сведения о заполнении холодильника, потому что ожидаете наличия поля fridge в структуре объекта, а не потому, что переменная называется smartHouseState . Выяснив, что в структуре объекта нет поля fridge вы смело можете сказать, что значение переменной cusomerInQueue не связано с управлением умным домом, и наоборот наличие такого поля в переменной smartHouseState подсказывает вам, что её значение описывает умный дом. Такой подход, когда о назначении значения вы судите по его структуре, называется структурной типизацией.
Иногда вы знаете структуру значения (потому что знаете), а иногда вам приходится как-то догадываться. Но как, ведь typeof в этой ситуации не поможет?
Object.keys и другие шпионские средства
JavaScript предоставляет вам ряд средств и сервисов, с помощью которых вы можете исследовать значение и принимать решение, как его обрабатывать.
Основными помощниками в исследовании полученных данных вам будут
- Статический метод Object.keys
- Оператор typeof
- Оператор instanceof
- Статический метод Object.hasOwn
const someValue = < title: 'Cruella', release: new Date(2021,05,03), empty: undefined, >console.log('all keys', Object.keys(someValue)); // "all keys", ["title", "release", "empty"] console.log('typeof key release', typeof someValue.release); // "typeof key release", "object" console.log('instance of Date', someValue.release instanceof Date) // "instance of Date", true console.log('missing value', typeof someValue.empty); // "missing value", "undefined" console.log('missing key', Object.hasOwn(someValue, 'missing')); // "missing key", falseПроблемы типов JavaScript
Динамическая структурная типизация JavaScript имеет давнюю историю и восходит к идее создания небольших обработчиков событий в статических HTML страницах. С тех пор все поменялось, и динамическая типизация становится серьезным риском при постепенном и постоянном совершенствовании приложения.
Например, у нас была функция transform . Мы обнаружили, что она ломается при получении значения null .
const transform = (value) => value.replace('с', 'б'); let data = 'соль' console.log(transform(data).toUpperCase()) // "БОЛЬ" data = null; try < console.log(transform(data).toUpperCase()) // не выполнится >catch (err) < console.log(err.message) // "Cannot read properties of null (reading 'replace')" >Исправили программу в одном месте — она начала ломаться в другом. Как разорвать замкнутый круг?
const transform2 = (value) => < if (typeof value === 'string') < return value.replace('с', 'б'); >> data = 'соль'; console.log(transform2(data).toUpperCase()) // "БОЛЬ" data = null try < console.log(transform2(data).toUpperCase()) >catch (err) < console.log(err.message) // "Cannot read properties of undefined (reading 'toUpperCase')" >Вам поможет TypeScript! Но об этом в следующий раз.
Узнать больше
- Что нужно знать фронтендеру, кроме JavaScript
- 12 полезных книг по JavaScript
- Зачем фронтендерам React, если есть JavaScript
- TypeScript. Зачем он нужен и почему так популярен
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.
Особенности типов данных и преобразования в JavaScript
На первый взгляд тема типов данных и преобразований может показаться легкой.
Обычно она изучается в самом начале погружения в JavaScript. Однако в этих темах есть неочевидные подводные камни, которые знает далеко не каждый разработчик.
В этой статье мы рассмотрим особенности типов данных и преобразований, которые многие пропустили.
typeof
JavaScript имеет 8 встроенных типов данных:
Подробности о каждом типе данных вы можете причитать в любой документации.
Значения typeof отличаются:
- ”undefined”
- ”boolean”
- ”number”
- ”string”
- object”
- ”symbol”
- ”function”
- «bigint»
Оператор typeof возвращает строку, указывающую тип операнда.
Операнд – то, к чему применяется оператор. Например, в умножении 5 * 2 есть два операнда: левый операнд равен 5 , а правый операнд равен 2 .
Оператор typeof напрямую не коррелирует со встроенными типами!
typeof null
Давайте рассмотрим пример:
const a = null; console.log(!a && typeof a === "object");В консоль будет выведено значение true .
Такой результат будет из-за того, что JavaScript имеет старый баг.
typeof null возвращает «object» .
Этот баг существует уже много лет и вероятнее всего уже никогда не будет исправлен. Это связано с тем, что написано слишком много кода, который полагается на это ошибочное поведение.
typeof function
Что будет выведено в консоль?
const x = function() <> console.log(x.length) // 0 const y = function(a, b, c) <> console.log(y.length) // 3У многих людей, которые не встречали такого вопроса ранее, может возникнуть недоумение. Учитывая, что typeof y и typeof x возвращает “function” , кто-то может ожидать, что функция является одним из встроенных типов в JS. На самом деле, согласно спецификации, функция — это подтип объекта. Благодаря этому можно проверить количество аргументов у функции через .length
typeof NaN
Важно запомнить особенности NaN :
-
NaN никогда не равен сам себе независимо от того используем мы == или === .
NaN === NaN // false NaN == NaN // falsewindow.isNaN(2 / "Dave") // true window.isNaN("Dave") // trueNumber.isNaN(2 / "Dave") // true Number.isNaN("Dave") // falseЗначение vs Ссылка
Вспомним простые значения в JS:
Простые значения в JS имутабельные. Комплексные значения мутабельные.
Сначала повторим разницу между мутабельными и имутабельными данными.
// Пример имутабельности чисел: let a = 1 let b = a b++ console.log(a) // 1 console.log(b) // 2 // Пример мутабельности: let x = [1, 2, 3] let y = x y.push(4) console.log(x) // [1, 2, 3, 4] console.log(y) // [1, 2, 3, 4] x.push(5) console.log(x) // [1, 2, 3, 4, 5] console.log(y) // [1, 2, 3, 4, 5]В примере мутабельности мы определили массив x . Константе y мы присвоили ссылку на х . Когда мы модифицируем массив x , мы также модифицируем и y .
При работе с имутабельными данными такого эффекта не происходит. Это важно запомнить!
Мы рассмотрели пример с числами. Давайте взглянем на пример со строками:
// Имутабельные строки: let a = "hello" a[2] = "Z" console.log(a) // "Hello"В данном примере не произойдет изменение строки!
Если вы хотите изменить строку, то вам придется создать новую переменную.
С использованием метода .toUpperCase() ситуация будет отличаться.
a.toUpperCase() console.log(a) // "HELLO"Метод .toUpperCase() возвращает новую строку и присваивает переменной a .
Взглянем, как ведут себя массивы со строками:
// Мутабельные массивы: let b = ["h", "e", "l", "l", "o"] b[2] = "Z" console.log(b) // ["h", "e", "Z", "l", "o"]Тут мы получили модифицированный массив b .
После повторения разницы между мутабельными и имутабельными данными может возникнуть вопрос: “Откуда у примитивных данных есть полезные методы вроде .toUpperCase() ?”
Если движок JavaScript встречает запись подобную «hello».toUpperCase() и у нас есть примитив, то мы вызываем у него метод. В таком случае вокруг примитива создается обертка в виде объекта, у которого как раз есть методы. После выполнения инструкции обертка удаляется и у нас снова остается примитивное значение.
Давайте рассмотрим легкий пример:
let a = [0, 1] let b = a b[0] = "a" console.log(a) // ["a ", 1]После повторения теории результат выполнения будет очевидным.
Но существует особенность в другом похожем примере:
let a = [0, 1] let b = a b = ["a", "b"] console.log(a[0]) // 0Переменной a мы присвоили массив.
Переменной b мы присвоили ссылку на переменную а , а затем переменной b присвоили новый массив.
В момент последнего присвоения старая ссылка была удалена!
Если мы создали новую ссылку в b , то мы уже не можем, модифицируя b , изменять и a .
let a = [0, 1] let b = a // Создается ссылка b = ["a", "b"] // Создается НОВАЯ ссылка на массивСравнение типов
Преобразование может быть явным, когда мы целенаправленно приводим один тип к другому, либо неявным, когда приведение типа происходит автоматически без явных команд.
String("123") // Явное преобразование 123 + "" // неявное преобразованиеВ JavaScript преобразование всегда приводит к 3м типам:
- к строке
- к числу
- к логическому значению ( true / false )
Приведение к строке
String(null) // "null" String(undefined) // "undefined" String(true) // "true" String(false) // "false" String(1) // "1" String(NaN) // "NaN" String(10000000000 * 900000000000) // "9e+21" String(<>) // "[object Object]" String(< name: "Ivan" >) // "[object Object]" String([]) // "" String([1, 2, 3]) // "1,2,3"В данном примере преобразование происходит очевидным образом.
Приведение к числу
Number(null) // 0 Number(undefined) // NaN Number(true) // 1 Number(false) // 0 Number(1) // 1 Number(NaN) // NaN Number(10000000000 * 900000000000) // 9e+21 Number(<>) // NaN Number(< name: "Ivan" >) // NaN Number([]) // 0 Number([1, 2, 3]) // NaN Number("Ivan") // NaN Number("0") // 0 Number("123") // 123Тут есть исключения, которые нужно помнить:
- Number(null) приводится к 0
- Number(undefined) приводится к NaN
- Пустой массив Number([]) приводится к 0
- Не пустой массив Number([1, 2, 3]) приводится к NaN
Приведение к логическому типу
// Ложные значения Boolean(null) // false Boolean(undefined) // false Boolean(NaN) // false Boolean(-0) // false Boolean(+0) // false Boolean("") // false // Истинные значения Boolean(1) // true Boolean(-1) // true Boolean(10000000000 * 900000000000) // true Boolean(<>) // true Boolean(< name: "Ivan" >) // true Boolean([]) // true Boolean([1, 2, 3]) // true Boolean(() => <>) // true Boolean("Ivan") // true Boolean("0") // trueВ этом примере стоит заострить внимание на объектах и массивах.
Пустая функция, объект или массив приведет к true .
Приведение комплексных данных
Комплексные данные, такие как объекты и массивы, сначала будут преобразованы в их примитивные значения, а уже потом это значение будет преобразовано в число.
Разберем более подробно. Если у объекта доступен метод .valueOf , который возвращает примитивное значение, то оно будет использоваться для приведения к числу, а если нет, то будет использоваться метод .toString() .
Если ни одна операция не может предоставить примитивное значение, то выдается ошибка “Type Error”
let x = <> x.valueOf = () => 22 console.log(Number(x)) // 22 let y = [] y.toString = () => '22' console.log(Number(y)) // 22 let z = <> z.valueOf() // <> (не примитив) z.toString() // "[object Object]" (приводит объект к строке) Number(z) // NaNДавайте коснемся логических операторов прежде чем продолжить дальше:
Как вы думаете что будет выведено в консоль?
let obj = < a: < b: "c" >> console.log(obj.a && obj.a.b)Казалось бы простой вопрос, но не все ответят правильно.
В консоль будет выведено с . Особенно для тех, кто пришел из других языков такой результат будет неочевиден.
Вспомним как работают логические операторы:
let a = 1 let b = "a" let c = null console.log(a && b) // "a" console.log(a || b) // 1 console.log(b || c) // null console.log(c || a) // 1Если оба операнда истины, тогда будет возвращен последний операнд.
Строгое сравнение и сравнение с приведением типов
Обычно считается, что === использует “строгое” сравнение, и сравнивает типы, а == нет.
Если говорить более корректно, == позволяет делать приведение типов, тогда как === не разрешает.
Таблицы ниже показывают в результатах между == и ===

Неявное приведение между строкой и числом
Можно неявно привести строку к числу, используя оператор + .
В JS оператор + используется как для сложения чисел, так и для конкатенации строк.
Оператор + выполняет операцию .toPrimitive над значением левой и правой стороны.
Метод .toPrimitive вызывает valueOf у значения. Если одно из значений является строкой, то он их объединяет.
Также существует небольшая разница между неявным приведением числа к строке с помощью + и явным с помощью String() .
+ вызывает valueOf , в то время как явный метод вызывает toString
Искусственный пример. Не берите его в свой код. Пример только для наглядности:
a = < valueof: () =>22, toString: () => 44 > String(a) // 44 a + '" // 22Алгоритмы сравнения
Нас интересует, что происходит, когда boolean находится по обе стороны от == .
console.log("22" == true) // false console.log("22" == 1) // false console.log(22 == 1) // falseВы могли ожидать, что «22» == true вернет true , т.к. “22” является истинным значением, но фактически результат будет false .
Это происходит из-за того, что значение true приводится к числу. Результат выполнения будет 1 . Далее «22» приводится к числу 22 . В конце идет сравнение 22 == 1 , где и возвращается false .
Задачи на собеседованиях
Мы готовы рассмотреть интересные примеры, которые встречаются на собеседованиях.
console.log(false == "0") // true // false приведен к 0 // "0" приведен к 0 // 0 === 0 console.log(false == 0) // true // false приведен к 0 // 0 === 0 console.log(false == "") // true // false приведен к 0 // "" приведен к 0 // 0 === 0 console.log(false == []) // true // false приведен к 0 // [] это объект так что вызывается ToPrimitive // valueOf() попробует получить примитивное значение // [].valueOf() приведет к [], что не является примитивным значением // При вызове [].toString() получим "" // "" будет приведео к числу 0 // 0 === 0 console.log("" == 0) // true // "" будет приведено к 0 // 0 === 0 console.log("" == []) // true // [] это объект так что вызывается ToPrimitive // valueOf() попробует получить примитивное значение // [].valueOf() приведет к [], что не является примитивным значением // При вызове [].toString() получим "" // "" === "" console.log(0 == []) // true // [] это объект так что вызывается ToPrimitive // valueOf() попробует получить примитивное значение // [].valueOf() приведет к [], что не является примитивным значением // При вызове [].toString() получим "" // "" приведен к 0 // 0 === 0Более сложные примеры
Операнд — то к чему применяется оператор.
Бинарный оператор — оператор, который применяется к 2м операндам ( 1 + 3 )
Унарный оператор — оператор, который применяется к одному операнду ( 2++ )
console.log(true + false) // 1 // Бинарный оператор + вызывает численное преобразование для true и false // 1 + 0 (вернет 1) console.log(12 / "6") // 2 // Оператор деления вызывает численное преобразование // 12 / 6 (вернет 2) console.log("number" + 15 + 3) // "number153" // Тут + выполняется слева направо // "number" + 15 (вернет "number15") // Поскольку один из операндов + это строка, то второе число будет преобразовано в строку // "number15" + "3" (вернет "number153") console.log(15 + 3 + "number") // "18number" // 15 + 3 (вернет 18) // 18 + "number" (вернет "18number") console.log([1] > null) // true // Оператор сравнения вызывает численное преобразование // [1] будет преобразован в 1 // null будет преобразован в 0 // 1 > 0 (вернет true) console.log("foo" + +"bar") // "fooNaN" // Унарный оператор имеет более высокий приоритет, чем унарный оператор // +"bar" выполнится первый // Унарный плюс вызывает численное преобразование "bar" (вернет NaN) // "foo" + NaN тут так же сработает конкатинация (вернет "fooNaN") console.log("true" == true) // false // Оператор сравнения вызывает численное преобразование // Левый операнд "true" преобразуется в NaN // Правый операнд true станет 1 // NaN === 1 (вернет false) console.log("false" == false) // false // Оператор сравнения вызывает численное преобразование // Левый операнд "false" преобразуется в NaN // Правый операнд true станет 0 // NaN === 0 (вернет false) console.log(null == "") // false // Оператор == обычно вызывает численное преобразование, но не в случае с null // null == null и null == undefined возращает true, а все остальные случаи вернут false console.log(!!"false" == !!"true") // true // Оператор !! конвертирует строки "false" и "true" в булевые значения // Получаем true == true, т.к. "false" не пустая строка (вернет true) console.log(["x"] == "x") // true // Оператор == вызывает численное преобразование у массива // Метод массива valueOf возвращает сам массив. Этот результат игнориуется, т.к. не является примитивом // Далее вызывается метод массива toString, который конвертирует ["x"] в "x" // "x" == "x" (вернет true) console.log([] + null + 1) // "null1" // Оператор + вызывает численное преобразование массива // Метод массива valueOf возвращает сам массив. Этот результат игнориуется, т.к. не является примитивом // Далее вызывается метод массива toString, который конвертирует [] в "" // "" + null (вернет "null") // "null" + 1 (вернет "null1") console.log([1, 2, 3] == [1, 2, 3]) // false // В данном примере преобразование не происходит, т.к. оба массива одного типа // Оператор == сравнивает объекты по ссылке, а не по значению // Данные массивы являются двумя разными экземплярами // Поэтому [1, 2, 3] == [1, 2, 3] вернет falseПользуясь возможность возможностью хотелось бы рассказать о youtube канале Open JS на котором выкладываются обучающие ролики по JavaScript. Ни какой воды, рекламы и пустых рассуждений. Канал только начал свое развитие. Буду рад поддержке!
Спасибо за внимание!
- javascript
- типы данных
- преобразование данных
- приведение типов
