深入理解ES6-10.数组改进

23 阅读4分钟

创建数组

Array.of

由于使用 new Array 创建数组时存在不统一的使用方法,当传入一位数值型参数时,默认这个传入的值为数组的 length,但是当传入的值不是数值型,或者传入多个参数,则这个参数会被认为是数组的元素添加进去。为了弥补这个缺陷,es6提供了 Array.of ,无论传入什么参数,总会创建一个包含所有参数的数组。

Array.of 不通过 Symbol.species 确定返回值类型,仅使用当前构造函数返回。

class MyArray extends Array{
    static get [Symbol.species](){
        return Array;
    }
}
let arr = MyArray.of('1,3');   // MyArray ["1,3"]

Array.form

es5 中想将类数组转换为数组,可以使用循环,或者 Array.prototype.slice.call(...) ,但是都不是很方便。所以,es6提供了 Array.from,它接收三个参数:

  1. 可迭代对象或类数组对象
  2. 可选,作用于类数组对象中每一项的函数,会将经过函数处理后的结果存储在生成的数组中
  3. 可选,为第二个参数函数指定 this 值。

定型数组

定型数组用于处理数值类型数据的专用数组,提供更高性能的算数运算,占用更少的存储空间。支持存储8种不同的数值类型:

  1. 有符号的8位整数 (int8)
  2. 无符号的8位整数 (uint8)
  3. 有符号的16位整数 (int16)
  4. 无符号的16位整数 (uint16)
  5. 有符号的32位整数 (int32)
  6. 无符号的32位整数 (uint32)
  7. 32位浮点数数 (float32)
  8. 64位浮点数数 (float64)

数据缓冲区

可以通过 ArrayBuffer 构造函数来创建数组缓冲区,参数为数组缓冲区应含的比特数量,且确定之后不能改变

let buffer = new ArrayBuffer(10)  // 分配10字节
buffer.byteLength = 8           // 无效,仍为10

可以通过 slice() 方法分割已有的数组缓冲区来创建一个新的。

视图

视图可以操作数组缓冲区,进行读取和写入, DataView 类型是一种通用的数组缓冲区视图。DataView 上也提供对应28种数值类型的操作方法。

let buffer = new ArrayBuffer(2)
let view = new DataView(buffer);
view.setInt8(0,5);         // 在第0位写入5,占据8位也就是1个字节
view.setInt8(1,-1);       // 在第1位写入-1,占据8位也就是1个字节

view.getInt8(0)       // 读取第0位开始放置的1个字节的数值:5
view.getInt16(0)      // 1535

我们使用同样的类型进行读取写入可以得到同样的结果,但是我们也可以混用不同类型的读取写入。

为什么是1535

偏个题,为什么这里使用getInt16(0)得到的是1535呢?就不得不说说原码、反码、补码、移码。原码就是我们所能理解的2进制表达形式,而计算机中使用补码存储数据。

  1. 最高位表示正反,0为整数,1为负数
  2. 对于正数,原反补一样
  3. 对于负数,反码是原码除符号位取反,补码是反码加1。
  4. 移码是在反码的基础上,符号位取反 | 值 | 原码 | 反码 | 补码 | 移码 | | --- | --- | --- | --- | --- | | 5 | 00000101 | 00000101 | 00000101 | 10000101 | | -1 | 10000001 | 11111110 | 11111111 | 01111111 |

所以最后存储在计算机内的16位数值:0000010111111111,换算一下就可以得到1535。

定型数组是视图

定型数组是用于数组缓冲区的特定类型数组,可以强制使用特定的数据类型,而不是像 DataView 那样可以混用,同样有对应8种不同的数值类型的视图:

Int8ArrayUint8ArrayUint8ClampedArrayInt16ArrayUint16ArrayInt32ArrayUint32ArrayFloat32ArrayFloat64Array

  1. 使用 ArryBuffer 创建定型数组
let buffer = new ArrayBuffer(10) 
let ints = new Int16Array(buffer);
  1. 传入一个数字创建定型数组,表示数组中的元素数量。这种创建方式会默认创建一个数组缓冲区。
let ints = new Int16Array(2);  // 创建了2个16位的字符,也就是4个字节
  1. 传入一个可迭代对象创建定型数组,这种创建方式会默认创建一个数组缓冲区。
let ints = new Int16Array([25, 50]);  // 创建了含2个元素的定型数组
ints[0] // 25
ints[1]  //50