本文内容
Array.of()
这个方法实际上就是说,将传入的参数构造成一个数组
let arr = Array.of(3, '2');
console.log(arr.length); // 2
console.log(arr[0]); // 3
console.log(arr[1]); // 2
let arr = Array.of(3);
console.log(arr.length); // 1
console.log(arr[0]); // 3
console.log(arr[1]); // undefined
这个其实跟我们自己写数组字面量是一样的,只不过是一种函数的方式,可以将这个方法传递给其它函数来构造数组
Array.from()
这个方法接收一个可迭代对象或者类数组对象(具有数字下标属性、length属性的对象,例如 arguments 对象),返回一个数组。
function doSomething() {
let args = Array.from(arguments);
}
也可以再传入一个转换函数,将可迭代对象或者类数组对象里的每一项元素经过一个转换
function doSomething() {
let args = Array.from(arguments, value => value + 1, this);
}
这里就是将每个参数加 1 ,然后转换成数组
第三个参数是转换函数里的 this 值,我们可以不传递这个对象
find 和 findIndex
这两个方法都接收 2 个参数,一个是用于查找的回调函数,一个是回调函数绑定的 this 值(可选)
回调函数接收的参数如下
- 数组中的元素值
- 该元素的下标值
- 数组本身
与 map 的回调的参数是一样的
如果回调函数返回 true,则表示找到了,否则继续迭代,直到遍历完成了整个数组。
如果找到了匹配的值,find 方法将会返回该值,findIndex 方法将会返回该值的下标
如果没有找到匹配的值,find 方法将会返回 undefined,findIndex 方法将会返回 -1
let nums = [1, 2, 3, 4];
console.log(nums.findIndex(value => {
return value === 8;
})); // -1
console.log(nums.find(value => {
return value === 8;
})); // undefined
console.log(nums.findIndex(value => {
return value === 3;
})); // 2
console.log(nums.find(value => {
return value === 3;
})); // 3
fill
这个方法是在数组中填充值的
let nums = [1, 2, 3, 4];
nums.fill(1);
console.log(nums); // [ 1, 1, 1, 1 ]
如果只想填充一部分值,也可以传入开始下标和结束下标(包左不包右)
let nums = [1, 2, 3, 4, 5, 6, 7];
nums.fill(1, 2, 5); // 下标 2 到下标 4,也就是 3,4,5 被替换成 1
console.log(nums.join(',')); // 1,2,1,1,1,6,7
不传入结束下标,则是将开始下标开始的地方全部替换
如果下标是负值,例如 -1,那么会被当成 array.length - 1
copyWithin
let nums = [1, 2, 3, 4, 5, 6, 7];
console.log(nums.copyWithin(2, 1).join(',')); // 1,2,2,3,4,5,6
这个方法实际上是一个数组的移位操作
nums.copyWithin(2, 1) 表示:将数组从下标为 1 的地方开始,覆盖数组从下标为 2 开始的地方,最后的效果就是下标从 1 开始的地方,全部往右边移动覆盖了一样
我们可以传入第三个参数,用来控制想要重写的元素的数量
数组缓冲区
说白了,就是终于支持了控制单个字节的能力。一个数组缓冲区就是一块连续的内存,也就是一组连续的字节
let buffer = new ArrayBuffer(10); // 创建 10 个字节的缓冲区
console.log(buffer.byteLength); // 10
let newBuffer = buffer.slice(4, 6); // 切片,从原来的缓冲区截取 4 和 5 下标的字节
console.log(newBuffer.byteLength); // 2
slice 是切片方法,常规操作
视图
我们可以从缓冲区创建视图,说白了视图就是缓冲区的一个片段
let buffer = new ArrayBuffer(10); // 创建 10 个字节的缓冲区
let view = new DataView(buffer, 3); // 从第四个字节开始创建视图
console.log(view.byteLength); // 7
视图创建时可以传入第三个参数,表示截取的视图长度
视图有以下只读属性
- buffer:表示创建视图的那个数组缓冲区(原始的那一整块缓冲区)
- byteOffset:视图相对于缓冲区的偏移量,也就是我们创建视图的第二个参数
- byteLength:视图的长度
读取和写入数据
我们通过视图可以读取和写入数据,以下是读取和写入 int8 和 uint8 的方法
- getInt8(byteOffset, littleEndian):读取 byteOffset 后的 int8 类型
- setInt8(byteOffset, value, littleEndian):设置 byteOffset 处的 int8 类型
- getUint8(byteOffset, littleEndian):读取 byteOffset 后的 uint8 类型
- setUint8(byteOffset, value, littleEndian):设置 byteOffset 处的 uint8 类型
littleEndian 是布尔值,表示是否按照小端进行读取
这里的 API 也有读取和写入 32 或者 64 位浮点数的,只是换了后面的类型名称而已,不一一列举了
let buffer = new ArrayBuffer(2);
let view = new DataView(buffer);
view.setInt8(0, 5);
view.setInt8(1, -1);
console.log(view.getInt8(0)); // 5
console.log(view.getInt8(1)); // -1
console.log(view.getInt16(0)); // 1535
可以看出来,就是常规的缓冲区操作,主要是弥补了之前 JavaScript 操作字节的缺陷
特定类型的视图(定型数组)
上面的视图是个通用的视图,我们可以读取和写入任何类型。但是实际中,我们可能仅仅是需要写入和读取某种特定类型。(就像是 netty 里的 ByteBuf、LongBuf、IntBuf 等)
有以下的定型数组
- Int8Array
- Uint8Array
- Int16Array
- Uint16Array
- Int32Array
- Uint32Array
- Float32Array
- Float64Array
- Uint8ClampedArray 8位无符号整数(强制转换),与 Uint8Array 大致相同,区别是如果值小于 0 或者大于 255,Uint8ClampedArray 会分别将其转换成 0 或者 255,例如将 -1 转成 0,将 300 转成 255(也就是只转成这两个值的一个)
创建定型数组
第一种,跟创建通用视图差不多
let buffer = new ArrayBuffer(10);
let view1 = new Int8Array(buffer, 5, 2);
第二种,自己创建一个全新的缓冲区
let ints = new Int16Array(3);
console.log(ints.byteLength); // 6
console.log(ints.length); // 3
这里的传入的 3,表示我们想要创建的缓冲区应该包含 3 个 Int16,因此打印的 ints.byteLength = 6,每个 Int16 占用 2 个字节,一共 3 个所以是 6。而 length 表示的是 Int16 个数量
第三种方式,是传入其它的一些对象,将这些对象作为缓冲区的输入源,来创建一个定型数组,支持以下参数
- 一个定性数组:将这个定型数组进行内存复制,复制到一个新的我们创建的定型数组中
- 一个可迭代对象:调用对象的迭代器,将元素插入到新生成的定型数组中
- 一个数组:跟上面一样,将数组元素插到定型数组中
- 一个类数组对象:与数组一样
let ints = new Int32Array([1, '2']);
console.log(ints.byteLength); // 8
console.log(ints.length); // 2
console.log(ints[0]); // 1
console.log(ints[1]); // 2
定型数组的访问就跟普通数组一样
元素大小
定型数组有个属性,表示数组中每个元素的大小(字节数量)
- BYTES_PER_ELEMENT
console.log(Uint8Array.BYTES_PER_ELEMENT); // 1
console.log(Uint16Array.BYTES_PER_ELEMENT); // 2
console.log(Uint32Array.BYTES_PER_ELEMENT); // 4
与普通数组的差异
- 定型数组不继承 Array,使用 Array.isArray() 将返回 false
- 定型数组赋值不存在的下标时,将会被忽视
说白了,定型数组更像是一个固定了长度、元素类型的数组