深入理解 You Don't Know JS: ES6 集合类型详解
前言
在 JavaScript 开发中,数据集合的组织和访问是几乎所有程序的核心部分。从语言诞生之初,数组(Array)和对象(Object)就是我们构建数据结构的主要工具。ES6 引入了几种新的集合类型,为开发者提供了更强大、更高效的数据处理能力。
本文将深入探讨 ES6 中的 TypedArrays、Map、Set 以及它们的弱引用版本 WeakMap 和 WeakSet,帮助开发者更好地理解和使用这些重要的数据结构。
TypedArrays:处理二进制数据的利器
TypedArrays(类型化数组)实际上在 ES5 时期就已经存在,主要用于 WebGL 等场景。ES6 将其正式纳入语言规范,使其成为 JavaScript 的一等公民。
基本概念
TypedArrays 并不是存储特定类型值的数组,而是提供了对二进制数据的结构化访问机制。它由两部分组成:
- ArrayBuffer:原始的二进制数据缓冲区
- 视图(View):解释缓冲区数据的类型化数组
// 创建32字节(256位)的缓冲区
const buf = new ArrayBuffer(32)
buf.byteLength // 32
字节序问题
字节序(Endianness)指的是多字节数据在内存中的存储顺序,分为大端序(Big-Endian)和小端序(Little-Endian)。TypedArrays 会使用运行平台的字节序,这可能在不同系统间交换数据时造成问题。
可以通过以下方法检测当前环境的字节序:
const littleEndian = (function() {
const buffer = new ArrayBuffer(2)
new DataView(buffer).setInt16(0, 256, true)
return new Int16Array(buffer)[0] === 256
})()
多重视图
同一个缓冲区可以附加多个不同类型的视图:
const buf = new ArrayBuffer(2)
const view8 = new Uint8Array(buf)
const view16 = new Uint16Array(buf)
view16[0] = 3085
view8[0] // 13
view8[1] // 12
TypedArray 构造函数
ES6 提供了多种 TypedArray 类型:
- Int8Array/Uint8Array (8位有/无符号整数)
- Uint8ClampedArray (8位无符号整数,值固定在0-255)
- Int16Array/Uint16Array (16位有/无符号整数)
- Int32Array/Uint32Array (32位有/无符号整数)
- Float32Array (32位浮点数)
- Float64Array (64位浮点数)
TypedArray 与普通数组类似,但长度固定且元素类型一致。它们共享大部分数组方法,但不支持会改变数组长度的方法如 push/pop 等。
Map:真正的键值对集合
传统 JavaScript 对象作为键值对集合使用时有个重大限制:键只能是字符串。Map 解决了这个问题,允许使用任意类型的值作为键。
基本用法
const m = new Map()
const x = { id: 1 }, y = { id: 2 }
m.set(x, "foo")
m.set(y, "bar")
m.get(x) // "foo"
m.get(y) // "bar"
Map 操作方法
set(key, value)
:添加键值对get(key)
:获取值delete(key)
:删除键值对clear()
:清空Mapsize
:获取键值对数量
遍历Map
Map 提供了三种遍历方法:
// 遍历值
const vals = [...m.values()] // ["foo", "bar"]
// 遍历键
const keys = [...m.keys()] // [x, y]
// 遍历键值对
const entries = [...m.entries()]
// [[x, "foo"], [y, "bar"]]
WeakMap:弱引用Map
WeakMap 与 Map 类似,但有几点关键区别:
- 只接受对象作为键
- 键是弱引用(不影响垃圾回收)
- 没有遍历方法和size属性
const wm = new WeakMap()
const x = { id: 1 }
wm.set(x, "private data")
// 当x不再被引用时,wm中的条目会被自动清除
WeakMap 非常适合存储对象的私有数据或元数据,因为当对象被回收时,相关数据也会自动清除,避免内存泄漏。
Set:值唯一的集合
Set 类似于数组,但成员值都是唯一的:
const s = new Set()
s.add(1).add(2).add(1)
s.size // 2
s.has(1) // true
WeakSet:弱引用Set
WeakSet 与 Set 的区别:
- 只能存储对象值
- 值是弱引用
- 不可遍历
const ws = new WeakSet()
const x = { id: 1 }
ws.add(x)
ws.has(x) // true
总结
ES6 新增的集合类型为 JavaScript 开发者提供了更强大的工具:
- TypedArrays 提供了处理二进制数据的能力
- Map/Set 解决了传统对象和数组的限制
- WeakMap/WeakSet 提供了更好的内存管理
这些新特性使得 JavaScript 能够更好地处理复杂数据结构和内存敏感的场景,是每个现代 JavaScript 开发者都应该掌握的技能。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考