🔥 一文搞懂 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 个坑》 🚀

相关推荐
滕青山2 小时前
Base64编码/解码 核心JS实现
前端·javascript·vue.js
sww_10262 小时前
SAA ReactAgent工作原理
开发语言·前端·javascript
linux_cfan2 小时前
拒绝“黑屏”与“哑剧”:Web视频播放器UX体验与自动播放选型指南 (2026版)
前端·javascript·音视频·html5·ux
be or not to be2 小时前
假期js学习汇总
前端·javascript·学习
SuperEugene2 小时前
日期与时间处理:不用库和用 dayjs 的两种思路
前端·javascript
Highcharts.js3 小时前
如何根据派生数据创建钟形曲线图表?highcharts正态分布曲线使用指南:从创建到设置一文搞定
开发语言·javascript·开发文档·正态分布·highcharts·图表类型·钟形图
心.c4 小时前
虚拟滚动列表
前端·javascript·vue.js·js
NEXT064 小时前
深拷贝与浅拷贝的区别
前端·javascript·面试
PieroPc4 小时前
用html+css+js 写一个Docker 教程
javascript·css·docker·html