Головна сторінка / Блог / Мови програмування / JavaScript / Типи даних у JS: повний гайд для початківців

Типи даних у JS: повний гайд для початківців

Розуміння типів даних JavaScript — це основа, на якій будується робота будь-якого розробника: від першої програми «Hello, world!» до створення складних інтерфейсних програм. Всі операції: порівняння, обчислення, робота зі сховищами та налаштування інтерфейсів, так чи інакше спираються на знання типів даних та розуміння їх особливостей.

Ця стаття призначена для новачків у JavaScript. Ми розберемо, які типи даних підтримує мова, в чому між ними різниця, і як правильно їх використовувати на практиці. Прочитавши статтю ви будете вільно визначати типи даних, пояснювати різницю між примітивами та об'єктами, а також уникати типових помилок, пов'язаних із копіюванням та зберіганням значень.

Рекомендації щодо вивчення теми

Для поглибленого вивчення теми рекомендую такі джерела, які використовувалися для підготовки даної статті

  1. Ви не знаєте JS: Типи та граматика
    • Для кого: читається легко і новачками, і тим, хто щось знає.
    • Що всерединуі: сучасне та докладне пояснення підводних каменів роботи з типами з прикладами «з реального життя».
  2. ECMAScript Data Types and Values
    • Для кого: тим, хто хоче точності та не боїться англійської технічної документації.
    • Що всередині: офіційний стандарт, максимально коректно описані всі нюанси внутрішньої реалізації типів даних JavaScript.
  3. ECMAScript Overview
    • Для кого: для тих, хто не боїться специфікацій
    • Що всередині: огляд усієї архітектури стандарту ECMAScript, включаючи класифікацію даних.

Як JavaScript зберігає дані: примітиви та об'єкти

На момент написання статті стандарт ECMAScript підтримує 8 типів даних. З них 7 примітивних і лише 1 об'єктний, тобто складовий.

Що таке тип даних і навіщо це знати?

Тип даних визначає, що вміє робити конкретна змінна: чи можна її скласти з іншим числом, перевірити, чи порожній рядок, перебрати елементи або викликати як функцію. Фізично значення зберігаються по-різному, і це впливає на поведінку нашого коду при копіюванні змінних та роботі з пам'яттю.

Всі типи даних у JavaScript

  • Undefined - тип з єдиним значенням undefined. Зазвичай означає значення не встановлено.
  • Null — спеціальне «нічого», але вже явно надане змінній. Часто використовується для очищення вмісту.
  • Boolean - логічні значення: true і false.
  • Number — усі числа: цілі та дробові, включаючи NaNInfinity.
  • BigInt - великі цілі числа (що вийшли за межі типового Number - 2 ^ 53-1).
  • String - рядки, будь-які послідовності символів.
  • Symbol - унікальний і незмінний ідентифікатор. Найчастіше використовується як ключі в об'єктах.
  • Object - універсальний «контейнер», може зберігати будь-які колекції, складні структури, масиви, функції.

Чому важливо розрізняти примітиви та об'єкти?

Примітив (undefined, null, boolean, number, bigint, string, symbol) зберігається «за значенням»: присвоюючи одну змінну інший, ви копіюєте саме значення.

Об'єкти ж зберігаються «за посиланням»: при присвоєнні копіюється не сам об'єкт, а лише його «покажчик» на область пам'яті, де знаходиться об'єкт.

Приклад:

let a = 1;
let b = a; // b — this is a new primitive: if a changes, b will not change.

let obj1 = {x: 10};
let obj2 = obj1; // obj2 — this is a reference to the same object. By changing obj2.x, you will also change obj1.x.

Ця різниця часто стає причиною плутанини у новачків. Слідкуйте, коли копіюєте об'єкти - ви працюєте з однією і тією ж сутністю у пам'яті!

Як визначити тип значення у вашому коді: оператор typeof

Оператор typeof допомагає в розробці та налагодженні: він повертає рядок, що відповідає типу значення.

Приклади:

typeof undefined                // "undefined"
typeof true                     // "boolean"
typeof "42"                     // "string"
typeof 42                       // "number"
typeof BigInt("9007199254740991") // "bigint"
typeof Symbol()                 // "symbol"
typeof {a: 1}                   // "object"
typeof function(){}             // "function"

Важливо

Для null результат неочевидний: typeof null // "object". Це історична помилка стандарту, її треба знати.

Для масивів та функцій typeof повертає "object" і "function" відповідно, хоча обидва є підтипами об'єкта.

Декілька слів про кожен тип: що важливо пам'ятати на практиці

Undefined

Найчастіше отримуєте цей тип, якщо оголосили змінну, але не надали їй значення:

let a;
console.log(a);       // undefined
console.log(typeof a) // "undefined"

Boolean

Базовий інструмент для перевірки умов:

let isAdult = age > 18; // true or false

Number та BigInt

Number охоплює більшість потреб, але його точності не вистачить для дуже великих цілих чисел. Для роботи з великими числами використовуйте BigIntнаприклад, при обчисленнях з великими рахунками.

String

Для зберігання та обробки текстів - імена, описи, адреси і т.д.

Symbol

Використовується рідко, частіше для створення унікальних ключів в об'єктах чи бібліотечних абстракціях.

Null

Усвідомлена відсутність значення. Новачки часто плутають його з undefined. Головна відмінність: undefined - «значення ще не було встановлено», а null - Значення явно відсутнє (скинуто).

Object (і його підтипи)

Об'єкти це асоціативні контейнери

Найчастіше вони створюються за допомогою літералу об'єктів (фігурні дужки). Ключами в об'єктах є рядки або символи, а значеннями будь-які типи.

let user = {
  firstName: 'John',
  lastName: 'Doe',
  phone: '555-24-42'
};

console.log(user.firstName); // "John"
console.log(user['firstName']); // "John"

Функції – особливий вид об'єкту

Однією з ключових особливостей функцій є перевикористання коду. Ідея полягає в тому, що ми виносимо в них код, який необхідно виконати кілька разів у програмі, і викликаємо цю функцію там, де це необхідно.

Одним із способів створення функції є оголошення за допомогою ключового слова function, після якого йде ім'я функції. Тіло функції визначається у фігурних дужках. Викликати функцію можна за її ім'ям, після чого йдуть круглі дужки.

Функції є підтипом об'єкта і називаються об'єктом, що викликається (callable object). Познайомившись із функціями ближче, можна помітити, що з ними справді можна поводитися, як з об'єктами. Наприклад, у них є властивість «length», до якої можна звернутися через крапку після імені змінної, як ми робили це в об'єкті. Ця властивість говорить про кількість аргументів функції (передані дані). У нашому прикладі повернеться нуль.

function greet() { /* code */ }
console.log(typeof greet); // "function" (callable object)
console.log(greet.length); // 0

Масиви - впорядковані колекції

Масив, як і функція є підтипом об'єкта. Масиви також використовуються як сховище даних і можуть зберігати елементи різних типів, навіть інші масиви. У прикладі нижче ми оголосили масив за допомогою літералу масиву (квадратні дужки після знака дорівнює) і відразу ж визначили в ньому три елементи: число, рядок та інший масив.

let arr = [1, "2", [3]];
console.log(arr[0]); // 1
console.log(arr[2]); // [3]

Кожному елементу, збереженому в масив, присвоюється індекс (його номер за порядком, починаючи з нуля). Надалі елемент масиву може бути отриманий за цим індексом. У нашому прикладі ми запитуємо перший елемент масиву. Для цього використовуємо квадратні дужки після імені змінної, в які передаємо необхідний індекс, тобто нуль.

Масиви використовуються для будь-яких колекцій, де важливим є порядок елементів (наприклад, черга користувачів):

let userQueue = [
  {fullName: 'John Doe'},
  {fullName: 'Martha Stuart'},
  {fullName: 'Sam Sparks'}
];
let firstUserInQueue = userQueue[0];
console.log(firstUserInQueue.fullName); // "John Doe"

Кілька нескладних вправ щодо збереження різних типів даних у змінні для закріплення вивченого матеріалу:

Типові помилки та коментарі

  • Копіювання об'єктів. При виконанні let b = a (якщо a і b - об'єкти) ви копіюєте не сам об'єкт, а посилання на нього. Щоб скопіювати об'єкт за значенням, використовуйте, наприклад, Object.assign({}, obj) або spread-оператор {...obj}.
  • typeof null. Повертає "object", хоча сам null - Це не об'єкт. Просто запам'ятайте цю особливість, інакше можна помилитися під час перевірки значень.
  • Перевірка масиву. typeof arr для масиву повертає "object", а не "array". Для точної перевірки використовуйте Array.isArray(arr).

Короткий підсумок: запам'ятати та застосовувати

  • У JS існує 7 примітивних типів даних та один об'єктний, з якого «виростають» функції та масиви.
  • Головна відмінність: примітиви копіюються за значенням, об'єкти - за посиланням.
  • Для перевірки типу використовуйте оператор typeof, але пам'ятайте винятки (особливо з null та масивами).
  • Типи даних не абстракція, а щоденний інструмент: від вибору правильного типу залежить поведінка коду та його надійність.
  • Напрацюйте звичку розрізняти та правильно використовувати типи: це основа роботи зі змінними та об'єктами у будь-якому проекті.
Ukrainian
Перейдіть до верхньої частини