第十二章 增强的数组功能

78 阅读5分钟

新增的数组API

静态方法

  1. Array.of()

    返回一个数组,数组中的元素就是该函数传入的参数

     const arr1 = Array.of(10);      // [10]
     ​
     const arr2 = new Array(10);     // [empty × 10]
    
  2. Array.from()

    通过给定的类数组或可迭代对象来创建一个新数组,并将其返回

实例方法

  1. find(callback)

    返回满足条件的第一个元素,找不到则返回undefined

  2. findIndex(callback)

    返回满足条件的第一个元素的下标,找不到则返回-1

  3. fill(data)

    将数组的全部元素都填充为data

  4. includes(data)

    判断数组中是否存在data,使用Object.is()进行匹配

类型化数组

在JS中,无论是小数还是整数,都是使用64位的双精度浮点数来保存

因此当存储某些数时,会造成内存空间的浪费

 const arr = new Array(100).fill(0);
 ​
 // 虽然arr中存储的都是0,但却占用了6400bit的空间

类型化数组就是用于优化多个数字的存储

类型化数组分为:

  1. Int8Array:每个元素都是8位的有符号整数
  2. UInt8Array:每个元素都是8位无符号整数
  3. Int16Array
  4. UInt16Array
  5. ...
  6. Float32Array
  7. Float64Array

注意:

  • 类型化数组只能存储数字
  • 当类型化数组存储的数字超出所能表示的范围时,会自动舍弃其高位

创建类型化数组

使用构造方法
 new Int8Array(len);

刚刚创建出的类型化数组,数组元素均为0

 const arr = new Int8Array(10);      // [0 × 10]

可以使用byteLength查看类型化数组所占内存的字节数量

注意:类型化数组不同于普通数组,类型化数组的构造方法只会将传入的数字作为数组的长度,而不会把它当做数组的元素

构造方法中也可以传入其他类型化数组,此时,构造方法将返回一个全新的类型化数组

 const arr1 = new Int8Array(10);
 ​
 const arr2 = new Int8Array(arr1);
 ​
 console.log(arr1, arr2);            // [0 × 10] [0 × 10]
 console.log(arr1 === arr2);         // false
使用静态方法of
 Int8Array.of(...);

of方法会将参数作为类型化数组的元素

使用静态方法from
 Int8Array.from();

from中传入可迭代对象

类型化数组的操作

类型化数组也是可迭代对象,因此可以使用for of循环

类型化数组的操作和普通数组基本一致

 const arr = new Int8Array(10);
 ​
 arr[0] = 100;

不过类型化数组一旦创建,长度就不能更改,即不能增加和删除元素

类型化数组的一些方法,其返回的也是同类型的类型化数组

const arr1 = new Int8Array(10);

const arr2 = arr1.map((item)=>{
    return item * 2;
});

// arr2也是Int8Array的类型化数组

ArrayBuffer

ArrayBuffer就代表着一块固定大小的内存空间

创建ArrayBuffer

new ArrayBuffer(byteLength);

ArrayBuffer的实例成员

  • byteLength

    得到ArrayBuffer所占空间的字节数

    const ab = new ArrayBuffer(10);
    
    console.log(ab.byteLength);		// 10
    
  • slice(start, end)

    将原ArrayBuffer中的从start字节位置开始,到end字节位置为止,但不包含end字节位置的这段内存数据复制到新ArrayBuffer中,并将新ArrayBuffer返回

    新ArrayBuffer的byteLength为end - start

    start为起始字节,默认为0,end为结束字节,默认为byteLength

    slice方法不会改变原ArrayBuffer,它仅仅只是得到一个新的ArrayBuffer

    const ab1 = new ArrayBuffer(10);
    
    const ab2 = ab1.slice(3, 6);
    
    console.log(ab2.byteLength);		// 3
    

读写ArrayBuffer

ArrayBuffer本身不具有读写内存的功能,要想让其具备读写功能则需要配合其它对象进行使用

使用数据视图
创建数据视图
const view = new DataView(ArrayBuffer, byteOffset, byteLength);

如上,表示创建一个数据视图,该数据视图可以操作ArrayBuffer中从byteOffset个字节开始,共byteLength个字节的内存数据

byteOffset和byteLength超出有效值时会报错

写数据
  • view.setInt8(offset, data)

    表示针对view可操作的部分中,向后偏移offset个字节,将从该位置开始的之后8个bit的数据设置为data

  • view.setInt16(offset, data)

    表示针对view可操作的部分中,向后偏移offset个字节,将从该位置开始的之后16个bit的数据设置为data

  • view.setInt32(offset, data)

  • ...

读数据
  • view.getInt8(offset)

    得到view可操作的部分中,向后偏移offset个字节,取出从该位置开始的之后8个bit的数据

  • view.getInt16(offset)

    得到view可操作的部分中,向后偏移offset个字节,取出从该位置开始的之后16个bit的数据

  • view.getInt32(offset, data)

  • ...

使用类型化数组

类型化数组中有一个buffer属性,它其实就是一个ArrayBuffer,该ArrayBuffer中保存的就是类型化数组中的数据

若创建类型化数组时不为其指定ArrayBuffer,则类型化数组会为自己创建一个新的ArrayBuffer

若创建类型化数组时传递的参数是ArrayBuffer,则该类型化数组的buffer属性就为该ArrayBuffer,这也表示类型化数组对应的内存空间就是ArrayBuffer

将类型化数组的空间与ArrayBuffer对应后,对ArrayBuffer的读写,就变成了对类型化数组的读写

多个类型化数组可以对应同一个ArrayBuffer

const ab = new ArrayBuffer(10);

const arr1 = new Int8Array(ab);

const arr2 = new Int8Array(ab);

console.log(arr1.buffer === ab);				// true
console.log(arr2.buffer === arr1.buffer);		// true

将同一个ArrayBuffer与多个类型化数组关联后,其中一个类型化数组对ArrayBuffer的修改,会影响到其他类型化数组

arr1[0] = 10;

console.log(arr2[0]);							// 10

注意:这里是以Int8Array举例,因此操作ArrayBuffer时,每次操作的是一个字节,若将Int16Array与ArrayBuffer关联,则每次操作的是两个字节