第六章:集合引用类型
6.1 Object
- 使用字面量表示法定义对象时,并不会调用 Object 构造函数
- 详见第 8 章
6.2 Array
6.2.1 创建数组
- 使用字面量表示法定义对象时,并不会调用 Array 构造函数
- ES6 增加
Array.from()
:也可以传入字符串 - ES6 增加
Array.of()
:将一组参数转换为数组
console.log(Array.from("1234", x => x *= x));
console.log(Array.of(1, 2, 3, 4));
6.2.2 数组空位
- 具有不确定性,必要时建议使用
undefined
代替
6.2.3 数组索引
6.2.4 检测数组
instanceof
:只有一个全局作用域的情况下可用Array.isArray()
6.2.5 迭代器方法
- 返回值均为迭代器,可以用
Array.from()
获取数组
let a = ["a", "b", "c", "d"];
let keys = a.keys();
let values = a.values();
let entries = a.entries();
console.log(Array.from(keys));
console.log(Array.from(values));
console.log(Array.from(entries));
for (const [index, item] of a.entries()) {
console.log(index, item);
}
6.2.6 复制和填充方法
fill()
:可以指定开始和结束位置,不会改变数组长度copyWithin()
:(插入位置,复制开始位置,复制结束位置)
6.2.7 转换方法
- 数组中存在
null
或 undefined
时,join()
、toLocaleString()
、toString()
、valueOf()
中此项以空字符串表示
6.2.8 栈方法
6.2.9 队列方法
6.2.10 排序方法
sort((a,b)=>{})
- 返回值小于 0,a 应在 b 前
- 返回值等于 0,a 等于 b
- 返回值大于 0,a 应在 b 后
6.2.11 操作方法
concat(a)
a[Symbol.isConcatSpreadable] = false;
避免打平数组
slice(a, b)
:不包含结束位置
6.2.12 搜索和位置方法
1. 严格相等 ===
indexOf()
lastIndexOf()
includes()
2. 断言函数
find((element, index, array)=>{})
findIndex()
6.2.13 迭代方法
every()
:如果每一项都返回 true,则该方法返回 truefilter()
:返回每一个返回 true 的单项组成的数组forEach()
:无返回值map()
some()
:有一项返回 true 则该方法返回 true
6.2.14 归并方法
let values = [1, 2, 3, 4, 5];
let sum = values.reduce((prev, cur, index, array) => prev + cur);
console.log(sum);
6.3 定型数组 Typed Array
6.3.1 历史
- 最早为了提供 WebGL 需要的格式,实现了 Float32Array
6.3.2 ArrayBuffer
- Float32Array 是一种“视图”,允许 JavaScript 运行时访问一块名为 ArrayBuffer 的预分配内存。
- ArrayBuffer 是所有 TypedArray 及视图引用的基本单位
- ArrayBuffer 一经创建就不能再调整大小,所有二进制位初始化为 0
- ArrayBuffer 分配的内存可以自动回收
- 要读取或修改 ArrayBuffer 需要通过视图
const buffer = new ArrayBuffer(16);
console.log(buffer.byteLength);
6.3.3 DataView 视图
const buffer = new ArrayBuffer(16);
const dataView1 = new DataView(buffer);
const dataView2 = new DataView(buffer, 0, 8);
1. ElementType
类 型 | 字 节 |
---|
Int8 | 1 |
Uint8 | 1 |
Int16 | 2 |
Uint16 | 2 |
Int32 | 4 |
Uint32 | 4 |
Float32 | 4 |
Float64 | 8 |
const buffer = new ArrayBuffer(16);
const dataView = new DataView(buffer);
console.log(dataView.getInt8(0));
dataView.setFloat64(0, 255);
dataView.setFloat64(8, -255);
console.log(dataView.getFloat64(0));
console.log(dataView.getFloat64(8));
2. 字节序
- 区分为
大端
(阅读友好)和小端
- 默认为大端字节序,可以在 DataView 所有 api 方法末尾加 true 转换
- 计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的
3. 边界情况
6.3.4 定型数组
- 遵循系统原生字节序
- 特定于一种 ElementType
- 速度更快
const buffer = new ArrayBuffer(16);
const i32 = new Int32Array(buffer);
console.log(i32.length);
console.log(i32.byteLength);
const i16 = Int16Array.from([1, 2, 3]);
const f64 = Float64Array.of(1.1, 2.2, 3.14);
console.log(f64[2]);
console.log(Float64Array.BYTES_PER_ELEMENT);
1. 定型数组行为
2. 合并、复制和修改定型数组
3. 下溢和上溢
Uint8ClampedArray
:强制转换元素为 0 - 255
6.4 Map
6.4.1 基本 API
- 可以使用任何 JavaScript 数据类型作为键
const m = new Map([
["key1", "a1"]
]);
console.log(m.has('key1'));
console.log(m.get('key1'));
console.log(m.get('key2'));
m.set('key2', 2);
m.set('key3', { value: 3 });
console.log(m.get('key3'));
console.log(m.size);
m.delete('key2');
console.log(m.size);
m.clear();
console.log(m.size);
6.4.2 顺序和迭代
6.4.3 选择 Object 还是 Map
1. 内存占用
- 给定内存大小,Map 可以比 Object 多存储 50% 的键/值对
2. 插入性能
3. 查找速度
- Object 有时更好
- 浏览器可以优化类数组的 Object
4. 删除性能
6.5 WeakMap
6.5.1 基本 API
- 键只能是 Object 或继承自 Object 的类型
6.5.2 弱键
6.5.3 不可迭代键
6.5.4 使用弱映射
1. 私有变量
- 使用闭包和 WeakMap 可以在 JavaScript 中实现真正的私有变量
2. DOM 节点元数据
6.6 Set
6.6.1 基本 API
const s = new Set([1, 2, 3]);
console.log(s.has(1));
6.6.2 顺序和迭代
entries()
返回的每一项是一个包含两个重复元素值的数组
6.6.3 定义正式集合操作
6.7 WeakSet
6.7.4 使用弱合集
6.8 迭代与扩展操作