В JavaScript примітив (примітивне значення, примітивний тип даних) – це значення, котрі не є об’єктами і не мають методів. JavaScript має 7 примітивних типів даних:
- string
- number
- bigint
- boolean
- undefined
- null
- symbol
Незмінність (immutable) примітивів
Примітиви в JavaScript – immutable, тобто вони не можуть бути змінені. Важливо не плутати самі примітиви, зі змінними котрі містять значення примітив. Змінній може бути присвоєно нове значення, але поточне значення не може бути зміненим, так само як можуть бути змінені об’єкти, масиви або функції:
let value = 'Тарас';
value.toUpperCase(); // метод рядка не може змінити сам рядок
console.log(value); // OUTPUT: Тарас
value = 'Вадим'; // присвоювання дає змінній примітиву нове (не змінене) значення
console.log(value); // OUTPUT: Вадимlet numbers = [1, 3, 5, 7];
numbers.pop(); // метод масиву змінює масив
console.log(numbers); // OUTPUT: [ 1, 3, 5 ]Об’єкти-обгортки для примітивів
В JavaScript усі примітивні значення (крім null та undefined) мають об’єктні еквіваленти, які є обгортками для примітивів (String, Number, BigInt, Boolean і Symbol). Об’єкти-обгортки мають методи, котрі дозволяють маніпулювати примітивами.
Примітиви не мають методів, але поводяться так, ніби вони є. Коли доступ до властивостей здійснюється на примітивах, JavaScript автоматично упаковує значення в об’єкт-обгортку, та натомість отримує доступ до властивості цього об’єкта. Наприклад:
let value = "foo";
console.log(value.toUpperCase()); // OUTPUT: FOO
console.log(value); // OUTPUT: foo- змінна value має значення string (примітив). В момент виклику value.toUpperCase(), JavaScript неявно створює об’єкт-обгортку String (котрий знає значення нашого рядка), та викликає String.prototype.toUpperCase() для цього об’єкта.
- метод toUpperCase() запускається і повертає новий рядок. Спеціальний об’єкт обгортка видаляється, залишаючи тільки примітив, котрий був призначений змінній value.
Тепер перейдемо до поверхневого огляду кожного примітивного типу даних JavaScript. В прикладах для наочності я буду використовувати оператор typeof, котрий допомагає отримати поточний тип значення, що зберігається у змінній.
string
В JavaScript string – це послідовність з нуля або більше символів, що використовується для представлення тексту.
JavaScript має три види лапок для рядкових літералів:
- подвійні: “some text”
- одинарні: ‘some text’
- зворотні: `some text`
Подвійні та одинарні лапки є «простими» лапками. Між ними в JavaScript практично немає різниці.
Зворотні – це лапки «розширеної функціональності». Вони дозволяють вбудовувати змінні та вирази в рядок, загортаючи їх у ${…}. Приклад:
let name = "John";
let text = `Hello ${name}`;
console.log(typeof text); // OUTPUT: string
console.log(text); // OUTPUT: Hello Johnnumber
JavaScript використовує тип number для представлення як цілих чисел, так і чисел з плаваючою комою:
let numberOne = 100;
console.log(typeof numberOne); // OUTPUT: number
let numberTwo = 10.5;
console.log(typeof numberTwo); // OUTPUT: numberСлід звернути увагу, що JavaScript автоматично перетворює число з плаваючою комою на ціле число, якщо воно виглядає як ціле число:
let value = 10.0;
console.log(value); // OUTPUT: 10Причина полягає в економії використання пам’яті, оскільки значення з плаваючою комою використовує більше пам’яті, ніж ціле значення.
Крім звичайних чисел, існують так звані «спеціальні числові значення», які також належать до цього типу, але не є числами у звичному розумінні цього слова: Infinity, -Infinity та NaN.
Infinity представляє математичну нескінченність ∞. Це особливе значення, котре більше будь-якого числа.
Як приклад, Infinity можна отримати в результаті ділення на нуль:
console.log(5 / 0); // OUTPUT: InfinityNaN означає обчислювальну помилку. Це результат неправильної або невизначеної математичної операції, наприклад:
console.log('text' / 1); // OUTPUT: NaNМатематичні операції в JavaScript «безпечні». Наприклад можна ділити на нуль, поводитися з не числовими рядками як із числами, тощо. Скрипт не зупиниться з фатальною помилкою (не «помре»). В гіршому випадку буде отримано NaN, як результат виконання.
bigint
Тип bigint представляє цілі числа, більші за (2⁵³ – 1) (тобто 9007199254740991) та менші за -(2⁵³ – 1).
Щоб створити значення типу bigint, необхідно додати n у кінець числового літерала:
let value = 9007199254740991n;
console.log(typeof value); // OUTPUT: bigintТип bigInt було додано в JavaScript, щоб дати можливість працювати з цілими числами довільної довжини, без втрати точності. Оскільки технічно, тип number може зберігати великі цілі числа (до 1.7976931348623157 * 10³⁰⁸), але за межами безпечного діапазону цілих чисел ±(2⁵³- 1) буде втрата точності, через те що не всі цифри поміщаються у фіксовану 64-бітну пам’ять. Тому зберігається лише «приблизне» значення.
Наприклад, ці два числа (прямо за межами безпечного діапазону) збігаються:
console.log(9007199254740991 + 1); // OUTPUT: 9007199254740992
console.log(9007199254740991 + 2); // OUTPUT: 9007199254740992Але якщо використовувати bigInt, точність буде збережено:
console.log(9007199254740991n + 1n); // OUTPUT: 9007199254740992n
console.log(9007199254740991n + 2n); // OUTPUT: 9007199254740993nboolean
Булевий тип boolean може мати лише два значення: true (істина), або false (брехня).
Цей тип зазвичай використовується для зберігання значень так/ні: true означає «так, правильно», а false означає «ні, не правильно».
Наприклад:
let isActive = false;
console.log(typeof isActive); // OUTPUT: booleanboolean значення можуть бути результатом порівнянь:
let isGreater = 5 > 0;
console.log(isGreater); // OUTPUT: trueJavaScript також дозволяє перетворювати значення інших типів, у логічні значення true або false, за визначеними правилами.
Для перетворення значень інших типів у логічні значення, використовується функція Boolean(). Наприклад:
let nonEmptyString = 'text';
console.log(Boolean(nonEmptyString)); // OUTPUT: true
let emptyString = '';
console.log(Boolean(emptyString)); // OUTPUT: falseundefined
undefined – це примітивний тип, який має лише одне значення: undefined. За замовчуванням, коли змінну оголошено, але не ініційовано, вона має значення undefined.
Розглянемо наступний приклад:
let value;
console.log(value); // OUTPUT: undefined
console.log(typeof value); // OUTPUT: undefinedВажливо зазначити, що оператор typeof також повертає undefined значення, якщо викликати його для змінної, котра взагалі не була оголошена:
console.log(typeof undeclaredVar); // OUTPUT: undefined null
Тип null – це примітивний тип даних, котрий має лише одне значення: null. Наприклад:
let obj = null;
console.log(typeof obj); // OUTPUT: objectУ наведеному вище прикладі визначено, що значення змінної obj невідоме.
Те що операція typeof null повертає object, є відомою помилкою в JavaScript. Пропозиція щодо виправлення була відхилена, бо це може зашкодити збереженню сумісності. Звичайно, що null не є об’єктом. Це спеціальне значення з окремим типом.
В JavaScript null не є «посиланням на неіснуючий об’єкт» або «нульовим покажчиком», як у деяких інших мовах програмування. Це просто спеціальне значення, яке являє собою «нічого», «порожньо» або «значення невідоме».
Також може бути корисним ознайомитись: JavaScript – різниця між undefined та null
symbol
JavaScript представив новий примітивний тип symbol у ES6. На відміну від інших примітивних типів, тип symbol не має літеральної форми.
Щоб створити значення типу symbol, потрібно викликати функцію Symbol() наступним чином:
let symbolValue = Symbol();
console.log(typeof symbolValue); // OUTPUT: symbolТакож функції Symbol() можна передати опціональний рядок description, в якості аргументу:
let symbolValue = Symbol('ok');
console.log(symbolValue); // OUTPUT: Symbol(ok)
console.log(symbolValue.description); // OUTPUT: okdescription може бути корисним для налагодження програми.
Значення symbol є унікальними:
let value1 = Symbol('ok');
let value2 = Symbol('ok');
console.log(value1 === value2); // OUTPUT: falseХоча value1 і value2 містять однаковий description, це різні значення.
Основне призначення symbol – отримувати унікальне значення кожного разу, коли вони створюються. Можна думати про symbol, як про спеціальні токени, котрі гарантують унікальність (як наприклад UUID).
symbol часто використовуються для ідентифікації властивостей об’єктів, щоб уникнути конфліктів імен, оскільки жоден symbol не дорівнює іншому:
let name = Symbol();
let person = {
[name]: 'Jhon'
};
console.log(person[name]); // OUTPUT: JhonЦе був загальний огляд примітивних типів даних в JavaScript. Огляд кожного типу, з більш детальним розбором особливостей використання, потребує окремого запису.