🔥 一文搞懂 JavaScript 包装类(面试必考)

🔥 一文搞懂 JavaScript 包装类(面试必考)

📌 一句话理解

包装类(Wrapper Objects) = JavaScript 为原始类型 提供的临时对象包装,让原始值也能调用方法

javascript 复制代码
// 原始类型(没有方法)
const str = 'hello';

// 但可以直接调用方法(自动装箱)
str.toUpperCase(); // 'HELLO'

// 本质:JavaScript 临时创建了 String 对象
new String('hello').toUpperCase(); // 'HELLO'

📋 目录

markdown 复制代码
1. 什么是包装类
2. 5 种包装类详解
3. 自动装箱和拆箱
4. 常见陷阱
5. typeof vs instanceof
6. 面试高频题
7. 最佳实践

1️⃣ 什么是包装类?

原始类型 vs 对象类型

javascript 复制代码
// 6 种原始类型(Primitive Types)
typeof 'hello'      // 'string'
typeof 123          // 'number'
typeof true         // 'boolean'
typeof null         // 'object' (历史遗留 bug)
typeof undefined    // 'undefined'
typeof Symbol()     // 'symbol'
typeof 123n         // 'bigint'

// 原始类型没有方法,但...
'hello'.toUpperCase(); // ✅ 可以调用!

包装类的作用

arduino 复制代码
┌─────────────────────────────────────────────────────────────┐
│                    包装类工作原理                            │
├─────────────────────────────────────────────────────────────┤
│  1. 原始值 'hello'                                          │
│  2. 调用方法时 → 自动创建 String 对象(装箱)                 │
│  3. 执行方法                                                │
│  4. 销毁临时对象 → 返回原始值(拆箱)                         │
└─────────────────────────────────────────────────────────────┘

2️⃣ 5 种包装类详解

String 包装类

javascript 复制代码
// 原始字符串
const str = 'hello';

// 自动装箱(临时创建 String 对象)
const tempObj = new String('hello');

// 可用的方法
str.length;           // 5
str.toUpperCase();    // 'HELLO'
str.toLowerCase();    // 'hello'
str.slice(0, 3);      // 'hel'
str.split('');        // ['h', 'e', 'l', 'l', 'o']
str.trim();           // 去除空格
str.includes('ell');  // true
str.replace('h', 'H'); // 'Hello'

Number 包装类

javascript 复制代码
// 原始数字
const num = 123;

// 可用的方法
num.toString();       // '123'
num.toFixed(2);       // '123.00'
num.toPrecision(5);   // '123.00'
Number.isNaN(num);    // false
Number.isFinite(num); // true

// 特殊值
NaN.toString();       // 'NaN'
Infinity.toString();  // 'Infinity'

Boolean 包装类

javascript 复制代码
// 原始布尔值
const bool = true;

// 可用的方法(很少)
bool.toString();      // 'true'
bool.valueOf();       // true

BigInt 包装类(ES2020)

javascript 复制代码
// 大整数
const big = 123n;

// 可用的方法
big.toString();       // '123'
big.valueOf();        // 123n

Symbol 包装类(ES6)

javascript 复制代码
// 符号
const sym = Symbol('key');

// 可用的方法
sym.toString();       // 'Symbol(key)'
sym.valueOf();        // Symbol(key)
sym.description;      // 'key'

3️⃣ 自动装箱和拆箱

装箱(Boxing)

javascript 复制代码
// 原始值 → 对象
const str = 'hello';
const obj = new String(str);

// 自动装箱(调用方法时)
str.toUpperCase();
// 等价于
new String(str).toUpperCase();

拆箱(Unboxing)

javascript 复制代码
// 对象 → 原始值
const obj = new String('hello');
const str = obj.valueOf(); // 'hello'
const str2 = obj.toString(); // 'hello'

// 自动拆箱(运算时)
const numObj = new Number(123);
numObj + 1; // 124(自动拆箱为原始值)

装箱拆箱流程图

javascript 复制代码
┌─────────────────────────────────────────────────────────────┐
│                  自动装箱拆箱流程                            │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   原始值 'hello'                                             │
│       ↓                                                      │
│   调用方法 .toUpperCase()                                    │
│       ↓                                                      │
│   自动装箱 → new String('hello')                             │
│       ↓                                                      │
│   执行方法 → 'HELLO'                                         │
│       ↓                                                      │
│   自动拆箱 → 销毁临时对象                                     │
│       ↓                                                      │
│   返回结果 'HELLO'                                           │
│                                                              │
└─────────────────────────────────────────────────────────────┘

4️⃣ 常见陷阱 ⚠️

陷阱1:typeof 检测结果不同

javascript 复制代码
const str1 = 'hello';
const str2 = new String('hello');

typeof str1; // 'string' ✅ 原始类型
typeof str2; // 'object' ❌ 对象类型

str1 === str2; // false(类型不同)
str1 == str2;  // true(值相等,自动拆箱)

陷阱2:对象永远为 truthy

javascript 复制代码
const bool1 = false;
const bool2 = new Boolean(false);

if (bool1) {
    console.log('不会执行');
}

if (bool2) {
    console.log('会执行!❌'); // 对象永远为 true
}

// 正确做法
if (bool2.valueOf()) {
    console.log('不会执行');
}

陷阱3:属性赋值无效

javascript 复制代码
const str = 'hello';
str.customProp = 'test'; // ❌ 临时对象,赋值后立即销毁

console.log(str.customProp); // undefined

// 正确做法(使用对象)
const strObj = new String('hello');
strObj.customProp = 'test';
console.log(strObj.customProp); // 'test'

陷阱4:new String 创建的字符串

javascript 复制代码
const str1 = 'hello';
const str2 = new String('hello');

str1 === str1; // true
str2 === str2; // true
str1 === str2; // false(不同类型)

// 比较时
str1 == str2;  // true(自动拆箱)

陷阱5:数组的 typeof

javascript 复制代码
const arr = [1, 2, 3];
typeof arr; // 'object' ❌ 不是 'array'

// 正确判断
Array.isArray(arr); // true

5️⃣ typeof vs instanceof

typeof 操作符

javascript 复制代码
typeof 'hello'      // 'string'
typeof 123          // 'number'
typeof true         // 'boolean'
typeof undefined    // 'undefined'
typeof Symbol()     // 'symbol'
typeof 123n         // 'bigint'
typeof null         // 'object' ❌ 历史 bug
typeof {}           // 'object'
typeof []           // 'object' ❌
typeof function(){} // 'function'

instanceof 操作符

javascript 复制代码
'hello' instanceof String;    // false(原始类型)
new String('hello') instanceof String; // true

123 instanceof Number;        // false
new Number(123) instanceof Number;     // true

[] instanceof Array;          // true
{} instanceof Object;         // true

对比表

操作符 检测原始类型 检测对象类型 检测数组 检测 null
typeof ❌(都是 object) ❌(返回 object)
instanceof
Array.isArray()
Object.prototype.toString

万能类型检测

javascript 复制代码
function getType(value) {
    return Object.prototype.toString.call(value).slice(8, -1);
}

getType('hello');     // 'String'
getType(123);         // 'Number'
getType(true);        // 'Boolean'
getType(null);        // 'Null'
getType(undefined);   // 'Undefined'
getType([]);          // 'Array'
getType({});          // 'Object'
getType(function(){});// 'Function'
getType(new Date());  // 'Date'

6️⃣ 面试高频题

题1:输出什么?

javascript 复制代码
const s1 = 'hello';
const s2 = new String('hello');

console.log(typeof s1);
console.log(typeof s2);
console.log(s1 === s2);
arduino 复制代码
'string'
'object'
false

题2:输出什么?

javascript 复制代码
const str = 'hello';
str.name = 'test';
console.log(str.name);
javascript 复制代码
undefined
// 原因:临时对象被销毁,属性丢失

题3:输出什么?

javascript 复制代码
const bool = new Boolean(false);
if (bool) {
    console.log('true');
} else {
    console.log('false');
}
sql 复制代码
'true'
// 原因:对象永远为 truthy,即使是 new Boolean(false)

题4:如何正确判断类型?

javascript 复制代码
// 答案
const arr = [1, 2, 3];

// ❌ 错误
typeof arr === 'array';

// ✅ 正确
Array.isArray(arr);
Object.prototype.toString.call(arr) === '[object Array]';

题5:手写类型检测函数

javascript 复制代码
function getType(value) {
    if (value === null) return 'null';
    if (value === undefined) return 'undefined';
    return Object.prototype.toString.call(value).slice(8, -1);
}

// 测试
getType(null);           // 'null'
getType([]);             // 'Array'
getType(new Date());     // 'Date'
getType(/regex/);        // 'RegExp'

7️⃣ 最佳实践

✅ 推荐使用原始类型

javascript 复制代码
// ✅ 推荐
const str = 'hello';
const num = 123;
const bool = true;

// ❌ 避免
const str = new String('hello');
const num = new Number(123);
const bool = new Boolean(true);

✅ 类型转换

javascript 复制代码
// 转字符串
String(123);      // '123'
(123).toString(); // '123'

// 转数字
Number('123');    // 123
+'123';           // 123
parseInt('123');  // 123

// 转布尔
Boolean('');      // false
!!'hello';        // true

✅ 类型检测

javascript 复制代码
// 检测字符串
typeof str === 'string';

// 检测数组
Array.isArray(arr);

// 检测 null
value === null;

// 通用检测
Object.prototype.toString.call(value);

📊 包装类速查表

原始类型 包装类 创建方式 常用方法
string String new String('') toUpperCase(), slice(), split()
number Number new Number(0) toString(), toFixed(), toPrecision()
boolean Boolean new Boolean(false) toString(), valueOf()
bigint BigInt new BigInt(123n) toString(), valueOf()
symbol Symbol Symbol('key') toString(), valueOf(), description

🎯 总结

javascript 复制代码
┌─────────────────────────────────────────────────────────────┐
│                    包装类核心要点                            │
├─────────────────────────────────────────────────────────────┤
│  1. 包装类让原始类型可以调用方法(自动装箱)                  │
│  2. 5 种包装类:String、Number、Boolean、BigInt、Symbol       │
│  3. typeof 检测原始类型,instanceof 检测对象类型              │
│  4. 避免使用 new String/Number/Boolean 创建值                │
│  5. 对象永远为 truthy(包括 new Boolean(false))             │
│  6. 临时对象的属性赋值会丢失                                 │
│  7. 万能类型检测:Object.prototype.toString.call()           │
└─────────────────────────────────────────────────────────────┘

记住口诀原始类型包装类,调用方法自动装;typeof 检测原始值,instanceof 检测对象;new 创建是对象,原始值才最推荐!


觉得有用?请点赞 + 收藏,下期预告:《JavaScript 类型转换详解:隐式转换的 10 个坑》 🚀

相关推荐
GISer_Jing1 天前
TypeScript打造高效MCP工具与Skills开发
前端·javascript·typescript
用户5757303346241 天前
JavaScript 事件循环:宏任务与微任务执行顺序一图搞懂
javascript·react.js
YimWu1 天前
面试官:OpenCode Tool 工具系统了解吗?
javascript·ai编程
天若有情6731 天前
【原创发布】typechecker:一款轻量级 JS 模板化类型检查工具
开发语言·javascript·npm·ecmascript·类型检查·typechecker
A_nanda1 天前
vue实现走马灯显示文字效果
前端·javascript·vue.js
晴栀ay1 天前
一文详解JS中的执行顺序——事件循环(宏任务、微任务)
前端·javascript·面试
0vvv01 天前
JavaScript-1
javascript
张元清1 天前
React 19 Hooks:新特性及高效使用指南
前端·javascript·面试
清空mega1 天前
《Vue3 中 computed、watch、watchEffect 怎么用?响应式核心能力详解》
前端·javascript·vue.js
SuperEugene1 天前
前端-后端-产品-项目-运维:互联网项目协作全流程解析
运维·前端·javascript