JavaScript дозволяє працювати з примітивами (рядок, число, тощо) так, ніби вони об’єкти. Примітиви також забезпечені методами для роботи. Ми вивчимо їх найближчим часом, але спочатку подивимось як воно працює, бо все ж таки примітиви не є об’єктами (і тут ми краще це зрозуміємо).
Розгляньмо різницю між примітивами та об’єктами.
Примітив
- є значенням примітивного типу
- існує 7 типів примітивів:
string,number,bigint,boolean,symbol,nullтаundefined.
Об’єкт
- можна зберігати декілька значень як властивості.
- може бути створений за допомогою
{}, наприклад:{name: "Іван", age: 30}. В JavaScript існують й інші об’єкти: функції — це теж об’єкти.
Одна з цікавих речей щодо об’єктів полягає в тому, що ми можемо зберігати функцію як одну з його властивостей.
let john = {
name: "John",
sayHi: function() {
alert("Привіт, друже!");
}
};
john.sayHi(); // Привіт, друже!
Отже, ми створили об’єкт john з методом sayHi.
Існує багато вбудованих об’єктів, які працюють з датами, помилками, елементами HTML і т.д. Вони мають різні властивості і методи.
Але за все потрібно платити!
Об’єкти “важчі”, ніж примітиви. Вони вимагають додаткових ресурсів для підтримки внутрішньої обробки.
Примітив як об’єкт
Маємо парадокс, з яким зустрівся автор JavaScript:
- Є багато речей, які можна було б зробити з примітивом-рядком або числом. Було б дуже добре якби можна було викликати для примітивів відповідні методи.
- Примітиви повинні бути максимально швидкими та легкими.
Рішення, яке він придумав, вийшло трохи незграбним. Та все ж. Ось як це працює в JavaScript:
- Примітиви залишаються примітивами. В них, як і задумано, є лише одне значення.
- Але JavaScript дозволяє отримати доступ до методів та властивостей рядків, чисел, булеанів та символів.
- Для цього створюється спеціальний “об’єкт-обгортка” (англ. object wrapper) з додатковою функціональністю, який потім знищується.
Для кожного примітиву створюється своя “обгортка”: String, Number, Boolean, Symbol та BigInt. Ну й вони містять різні набори методів.
Наприклад: існує такий метод для рядка, як str.toUpperCase(), який поверне рядок str з великими літерами.
Ось як він працює:
let str = "Привіт";
alert( str.toUpperCase() ); // ПРИВІТ
Не складно, так? Ось що саме трапляється в str.toUpperCase():
- Рядок
strє примітивом. Тому в момент, коли треба звернутись до його властивості, створюється спеціальний об’єкт, який знає значення рядка і має корисні методи, такі якtoUpperCase(). - Цей метод виконується і повертає новий рядок (який передається в
alert). - Спеціальний об’єкт знищується, і в пам’яті залишається лише сам примітив
str.
Отже, примітиви можуть надавати методи, але залишаються “легкими”.
Рушій JavaScript добре оптимізує цей процес. Він навіть може взагалі пропустити створення додаткового об’єкта-обгортки. Але навіть в таких ситуаціях він поводиться так, наче він той об’єкт-обгортку створив.
Число має свої методи, наприклад: toFixed(n) – округлює число до заданої точності:
let n = 1.23456;
alert( n.toFixed(2) ); // 1.23
Ми переглянемо більш конкретні методи у розділах Числа та Рядки.
String/Number/Boolean існують лише для внутрішнього використанняДеякі мови як от Java дозволяють явно створювати “об’єкт-обгортку” для примітивів, використовуючи синтаксис new Number(1) або new Boolean(false).
У JavaScript це також можливо з історичних причин, але надзвичайно не рекомендується. Це призведе до непередбачуваних речей.
Наприклад:
alert( typeof 0 ); // "number"
alert( typeof new Number(0) ); // "object"!
В JavaScript об’єкти завжди повертають true в if, отже ми побачимо alert:
let zero = new Number(0);
if (zero) { // zero є true, тому що це об’єкт
alert( "zero є true!?!" );
}
З іншого боку, використання тих же самих функцій String/Number/Boolean, але без new попереду – це абсолютно розумно і корисно. Без new ці функції перетворюють значення у відповідний тип: рядок, число або булеве значення (яке буде примітивом).
Наприклад, це цілком правильно:
let num = Number("123"); // конвертує рядок в число
Примітиви null і undefined є винятками. Вони не мають відповідних “об’єктів-обгорток” і не забезпечені ніякими методами. Ми можемо назвати їх “найбільш примітивними”.
Спроба доступу до властивості такого значення дасть помилку:
alert(null.test); // помилка
Підсумки
- Примітиви (крім
nullіundefined) забезпечені багатьма корисними методами. Ми вивчимо їх у наступних розділах. - Формально, ці методи працюють через тимчасові об’єкти, але двигун JavaScript оптимізовано для швидкого виконання цих операцій, тому нам не треба хвилюватися.
Коментарі
<code>, для кількох рядків – обгорніть їх тегом<pre>, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)