nfssuzukaze / Blog

0 stars 0 forks source link

Array #27

Open nfssuzukaze opened 3 years ago

nfssuzukaze commented 3 years ago

1. JavaScript 数组并不是真正的数组

1.1 真正的数组

在 C/C++, Java 等语言中, 申请数组时会被分配一块连续的内存空间, 如下 image 对于真正的数组来说, 想要存取元素, 只需要获取元素所对应的下标 index 即可, 而后将 index 与数组的首地址相加即可获取元素对应的内存地址, 从而能够对该内存地址中的内容进行读写

1.2 JavaScript 的数组(哈希表)

在 JavaScript 中, 申请数组时分配的并不一定是一块连续的内存空间 要在 JavaScript 的数组中存取元素, 需要提供 value 所对应的 key, 而后由引擎先对 key 进行哈希操作获取真正的 key, 然后再通过该 key 获取哈希表中的 value 的内存位置, 从而进行读写

1.3 对比

2. JavaScript 内存连续的数组

JavaScript 内存连续的数组拥有连续的内存空间, 存取元素只需要提供相应的下标即可, 引擎会将下标与数组首地址进行相加操作获取对应的内存地址, 而后对该内存地址中的内容进行读写

2.1 类型化数组

let buffer = new ArrayBuffer(32) // 申请连续32字节的内存空间
let view = new Uint32Array(buffer) // 将该32字节的内存空间转换为由32位无符号整数所组成的数组

2.2 数组的自动转化

3. 内存连续的数组与哈希表模式下的数组性能对比

3.1 写:

image

const LIMIT = 1e7
let arr = new Array(LIMIT)
arr.push({a: 1})
console.time("hash")
for (let i = 0; i < LIMIT; i++) arr[i] = i
console.timeEnd("hash")

let newArr = new Array(LIMIT)
console.time("type")
for (let i = 0; i < LIMIT; i++) arr[i] = i
console.timeEnd("type")

3.2 读:

image

const LIMIT = 1e7

let arr = new Array(LIMIT)
for (let i = 0; i < LIMIT; i ++) arr[i] = i
let temp = 0
arr[LIMIT + 1024] = 1 // 转为 hashTable 模式
console.time("hash")
for (let i = 0; i < LIMIT; i ++) temp = arr[i]
console.timeEnd("hash")

let newArr = new Array(LIMIT)
for (let i = 0; i < LIMIT; i ++) newArr[i] = i
let newTemp = 0
newArr[LIMIT + 1024] = 1 // 转为 hashTable 模式
newArr[LIMIT + 1025] = 1 // 转为 array 模式
console.time("array")
for (let i = 0; i < LIMIT; i ++) newTemp = newArr[i]
console.timeEnd("array")