Коротка відповідь
juniorBoxing — це автоматичне створення об’єкта‑обгортки для примітиву, коли потрібен доступ до властивостей або методів. Unboxing — отримання первісного примітиву з об’єкта‑обгортки, коли потрібне значення. Це відбувається через внутрішні операції ToObject і ToPrimitive, що викликаються при доступі до властивостей або порівняннях.
Повне пояснення
Що це і навіщо
Boxing (обгортка) дозволяє примітивам, таким як number, string або boolean, поводитися як об’єкти, що дає доступ до методів (toString(), valueOf() тощо). Unboxing (розгортка) повертає первісне значення, коли потрібна арифметика або логічні порівняння.
Ключові принципи/терміни
ToObject– внутрішня операція, що створює об’єкт‑обгортку.ToPrimitive– внутрішня операція, що повертає примітив.- Об’єкти‑обгортки:
Number,String,Boolean. - Примітиви:
number,string,boolean,symbol,bigint.
Як це працює (логіка)
- При доступі до властивості примітива (
x.length) викликаєтьсяToObject(x)→ створюється об’єкт‑обгортка. - Методи або властивості викликаються на цьому об’єкті.
- Після завершення операції обгортка знищується (garbage‑collected).
- При арифметичних операціях або порівняннях (
+,==) викликаєтьсяToPrimitive→ отримується первісне значення.
Практика і реалізація (JS/TS)
const num = 42; // примітив
console.log(num.toString()); // boxing → Number object, then toString()
const str = 'hello';
console.log(str.length); // boxing → String object
let flag = true;
if (flag) console.log('ok'); // unboxing → boolean primitive
Тестування
import { expect } from 'chai';
describe('boxing/unboxing', () => {
it('should call toString on number', () => {
const spy = sinon.spy(Number.prototype, 'toString');
5.toString();
expect(spy.calledOnce).to.be.true;
spy.restore();
});
});
Альтернативи/порівняння
- У JavaScript обгортки створюються автоматично; в інших мовах (наприклад, Java) обгортки часто створюються явно (
Integer,String). - У TypeScript типи примітивів і об’єктних не розділяються в синтаксисі, але типи
Number,Stringіснують як інтерфейси.
Оптимізація та edge‑cases
- Часте використання обгорток може впливати на продуктивність через зайві алокації.
- Необхідно уникати порівнянь типу
==між примітивом і об’єктом‑обгорткою, бо це викликаєToPrimitiveі може призвести до неочікуваних результатів.
Часті помилки
new Number(5) == 5→ true, але об’єкт не еквівалентний примітиву.new String('a') === 'a'→ false, бо різні типи.- Використання
Object.is(new Number(5), 5)→ false. - Неочікуване
NaNприNumber(undefined). - Порівняння
0 == false→ true, черезToPrimitive. - Перетворення
Symbol('a') + ''→ TypeError. BigInt(10) == 10n→ true, але типи різні.new Boolean(false)в умовному операторі → true, бо об’єкт.
Дизайн‑рішення
- Якщо потрібна строгість типів, використовуйте
===і явно перетворюйте примітиви. - Для числових обчислень використовуйте
Number(value)або шаблонні літерали. - У бібліотеках, що працюють з великими даними, обмежуйте створення обгорток.
Cheatsheet
ToObject(prim)→ об’єкт‑обгортка.ToPrimitive(obj, hint?)→ примітив.- Методи:
valueOf(),toString(). - Порівняння:
==→ викликаєToPrimitive;===→ без перетворень.
Follow‑up питання
- Які ще внутрішні операції пов’язані з конвертацією типів?
- Як
Symbolповодиться під час boxing/unboxing? - Чому
new Boolean(false)в умовному операторі повертає true?