У JavaScript значення можуть мати різні типи. Змінити тип змінної можна за допомогою явного перетворення типу. Окрім цього, JavaScript також виконує приведення типу (неявне перетворення типу), коли цього вимагає контекст.
У JavaScript немає конструкції, щоб привести значення до (іншого) типу, як у багатьох інших мовах, але замість неї можна скористатися деякими вбудованими засобами.
Найпримітніше те, що глобальні обʼєкти Boolean, Number і String можна використовувати як функції, щоб перетворити значення на відповідний тип.
За допомогою Boolean(value) можна перетворити будь-яке значення на булеве значення (англ. Boolean).
Як це працює?
Існує фіксований набір значень, так званих хибних, які перетворюються на false.
Найважливіше те, що false, 0, порожній рядок тексту (англ. string), null, undefined і NaN є хибними.
Стаття MDN про хибні значення показує повний список.
Для всіх інших значень Boolean повертає true.
Такі значення називають істинними.
Boolean(-1);
// => true
Boolean(0);
// => false
Boolean(' ');
// => true
Boolean('');
// => false
Зауважимо, що через описані правила '0', 'false', [] і {} у JavaScript є істинними.
Number(value) можна використати, щоб перетворити значення на число.
Пробільні символи на початку та в кінці рядка тексту ігноруються, а порожній рядок тексту перетворюється на 0.
Якщо спробувати перетворити непримітивне значення або рядок тексту, що не є числом, жодної помилки не буде викинуто.
Натомість результатом буде NaN (не число).
Number(' -12.34 ');
// => -12.34
Number('1,2');
// => NaN
Number('1 2');
// => NaN
Number('');
// => 0
Number('10e3');
// => 10000
Number({ key: '123' });
// => NaN
Нижче можна побачити, що Number повертає для інших примітивних значень.
Number(true);
// => 1
Number(false);
// => 0
Number(null);
// => 0
Number(undefined);
// => NaN
Зауважимо, що на відміну від останнього прикладу, Number(), викликаний без жодного аргументу, визначений повертати 0.
JavaScript також надає функції parseInt і parseFloat.
Вони застосовують мʼякші правила щодо того, які рядки тексту можна перетворити на число.
Через це перевагу варто віддавати Number як функції перетворення, щоб уникнути несподіваних результатів.
parseInt('123a45');
// => 123
Number('123a45');
// => NaN
За допомогою String(value) можна перетворити значення на рядок тексту.
Для примітивних значень результат буде таким, як і очікується.
String(12.34);
// => '12.34'
String(false);
// => 'false'
String(null);
// => 'null'
String(undefined);
// => 'undefined'
Для масивів функція String застосує перетворення рядка тексту до кожного елемента й зʼєднає результати комою.
Можна також самостійно застосувати метод join, наприклад, щоб налаштувати роздільник.
Однак у цих випадках null і undefined перетворяться на порожній рядок тексту.
String([42, null, true, 'abc']);
// => '42,,true,abc'
Для обʼєктів String типово повертає не дуже корисний текст.
String({ key: 'value' });
// => '[object Object]'
Можна налаштувати поведінку перетворення, наприклад, надавши метод toString.
Розділ «Перетворення обʼєкта на примітив» на javascript.info пояснює подробиці.
Ще один поширений спосіб отримати краще подання у вигляді рядка тексту для обʼєктів і масивів - скористатися кодуванням JSON.
Можна перетворити на рядок тексту за допомогою JSON.stringify і назад на обʼєкт або масив за допомогою JSON.parse.
const obj = {
name: 'Gilda Guerra',
address: {
city: 'Goiânia',
},
};
JSON.stringify(obj);
// => '{"name":"Gilda Guerra","address":{"city":"Goiânia"}}'
У певних контекстах JavaScript автоматично перетворює значення на інший тип даних, перш ніж обчислити якусь інструкцію. Це неявне перетворення називають приведенням типу.
Коли значення використовується в булевому контексті, JavaScript застосовує ті самі правила, що й функція Boolean, щоб неявно перетворити його.
Коли умова умовної конструкції не є булевим значенням, застосовується приведення, щоб визначити, виконується умова чи ні.
Те саме стосується першого операнда тернарного оператора ?.
const num = 0;
if (num) {
// this block is NOT executed because 0 is falsy
}
const name = 'Jin';
name ? 'name was provided' : 'no name provided';
// => 'name was provided'
Операнд оператора логічного заперечення ! також приводиться до булевого значення, перш ніж застосовується сама операція заперечення.
const name = '';
!name;
// => true
Наслідком описаної поведінки є те, що !!value дає той самий ефект, що й Boolean(value).
Тим не менш, для читабельності варто використовувати Boolean.
JavaScript також застосовує приведення до операндів логічних операторів && (логічне і) та || (логічне або).
Але варто памʼятати, що результат виразу не обовʼязково є булевим значенням.
Він повертає один із початкових операндів (див. MDN про логічні оператори).
null || 'hello';
// => 'hello'
Якщо оператор додавання + застосовується до примітивних значень і один з операндів є рядком тексту, інший також буде приведений до рядка тексту.
Логіка перетворення така сама, як і під час використання функції String.
Після цього два рядки тексту зʼєднуються.
let name;
'hello ' + name;
// => 'hello undefined'
Те саме неявне перетворення відбувається зі значеннями, що не є рядками тексту, вбудованими в шаблонні рядки.
const degrees = 23;
`It is ${degrees} °C`;
// => 'Is is 23 °C.';
Багато операторів приводять операнди до чисел (за потреби) згідно з логікою функції Number, поясненою вище.
+ (якщо не задіяно рядок тексту), -, *, /, %, **
+, -
>, >=, <, <=
|, &, ^, ~
Докладніше про будь-який із цих операторів див. у списку операторів MDN.
Коли операнд потенційно може бути рядком тексту, найкраще завжди явно перетворювати його за допомогою функції Number, щоб уникнути помилок.
'1' + '2';
// => '12'
// addition operator in string context as explained above
Number('1') + Number('2');
// => 3
Іноді можна побачити, як унарний плюс використовують, щоб привести рядок тексту до числа.
Цього не рекомендують, бо це значно важче читати, ніж явний виклик Number.
const value = '42';
+value;
// => 42
Number(value);
// => 42
Використання операторів нестрогої рівності та нерівності ==/!= також часто передбачає неявне перетворення на число.
Однак точна логіка цих операторів досить складна (див. MDN про нестрогу рівність).
Результати важко передбачити, і іноді вони не такі, як очікується.
Натомість краще використовувати оператори строгої рівності/нерівності ===/!==, щоб уникнути цих неявних перетворень.