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

相关推荐
To_OC1 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
小林ixn2 小时前
从 ??= 到 onKeyDown:一个 React 组件的“自我修养”
前端·javascript·react.js
এ慕ོ冬℘゜2 小时前
前端实战:jQuery 多条件联合搜索(标题模糊查询 + 日历时间段筛选)
前端·javascript·jquery
随心点儿3 小时前
js postMessage 实现跨域发送消息-应用示例
javascript·ecmascript·postmessage
kyriewen4 小时前
我让AI改一个bug——它偷偷动了5个我没让它碰的地方
前端·javascript·ai编程
gis开发之家9 小时前
《Vue3 从入门到大神35篇》Vue3 源码详解(五):effect 依赖收集原理——track 与 trigger 是如何工作的?
javascript·typescript·前端框架·vue3·vue3源码
橘子星10 小时前
我一个前端切图仔,凭什么能在浏览器里跑大模型?
前端·javascript·前端框架
半个落月10 小时前
用 LangChain JS 做可控写作实验:理解温度参数、提示词与异步调用
javascript·人工智能·后端
观远数据10 小时前
Excel到数据资产池:文件数据入湖的治理规范怎么建
前端·javascript·excel
CoderWeen10 小时前
我写了个能一步步点着看的 Dijkstra 可视化项目(Vue3 + Leaflet + Generator)
前端·javascript·vue.js