如何在 JavaScript 中为数组分配内存?

How is memory allocated for arrays in JavaScript?

提问人:Vishal 提问时间:8/19/2023 更新时间:8/19/2023 访问量:47

问:

我希望下面的程序能够输出 40,000 字节(200 * 200 * 8 位数组或 1 个字节),但它在插入 .为什么?159800200

当它在插入 () 时输出,在插入 () 时输出时,即使它始终是 8 位数组,它也会变得更加混乱。11980010subArray[j][0]=10798001subArray[j][0]=1

如果我更改为,对于相同的数字,输出的值完全相同。Uint8Array(1)Uint16Array(1)

数组是如何工作的?

let x = 200
let y = 200

const changes =[]
for (let i=0;i<y;i++) {
    const subArray = []
    for (let j=0;j<x;j++) {
        subArray[j] = new Uint8Array(1);
        subArray[j][0]=200
    }
    changes[i]=subArray;
}

console.log(new Blob(changes).size);
JavaScript 内存管理 UTF-8 blob

评论

0赞 icecub 8/19/2023
尚不完全理解原因,似乎您在实例化对象时没有设置正确的长度参数。.如果将长度参数设置为 3(因为 200 是 3 个数字),结果将是 319800,这似乎更有意义Uint8Array200 * 200 * 8 = 320000
0赞 Pointy 8/19/2023
@icecub 8 是数,而 200 只是一个数字。
0赞 icecub 8/19/2023
@Pointy 没错。因此,我对为什么结果实际上在某种程度上有意义感到困惑。
0赞 Pointy 8/19/2023
@icecub,是的,问题中奇怪的“不同大小”的东西确实可以通过字符串“200”是 3 个字符和字符串“1”是一个字符来解释。(我没有做过算术。
0赞 user253751 8/23/2023
您是否考虑过检查 blob 中有哪些数据?它可能用十进制写所有数字

答:

4赞 Pointy 8/19/2023 #1

U 是一个普通的数组,恰好填充了 Uint8Array 实例。如果您更改代码,使其改为 200 字节的类型化数组,您将得到预期的答案:subArray

let x = 200
let y = 200

const changes =[]
for (let i=0;i<y;i++) {
    const subArray = new Uint8Array(200);
    for (let j=0;j<x;j++) {
        subArray[j] = 200;
    }
    changes[i]=subArray;
}

console.log(new Blob(changes).size); // 40000

该规范没有说明如果其中一个“blob 部分”是类型化数组的普通数组会发生什么。它可能正在将数组转换为字符串,但我不能说这在内部究竟是如何发生的。(e:实际上我可以,我想;见下文。

我要说的是规范,它说明了传递给 Blob 构造函数的“blob 部件”参数(在您的代码中)中的 3 种可能性会发生什么。每个部分可以是:changes

  1. 一个斑点;
  2. 缓冲区源(如类型化数组);
  3. 一个字符串。

所以没有提到“装满任何东西的普通阵列”。

编辑 — 如果你做一个小实验,很明显(嗯,很清楚)它正在将普通数组转换为字符串。这将需要将数组中的每个元素转换为字符串。使用值为 200 的单个字节转换 Uint8Array 时,将获得字符串“200”,即 3 个字符。当然,如果你用 10 进行初始化,你会得到“10”,而 1 会给你“1”。这(可能)解释了代码中的初始化值给出不同大小的答案这一事实:这是字符串值的大小差异,而不是字节。

let z = new Uint8Array([1, 2, 3]);
console.log(z[1]); // 2, as a number
let y = [z];
console.log(y.toString()); // '1,2,3' as a string
y = [z, z];
console.log(y.toString()); // '1,2,3,1,2,3'

评论

0赞 Vishal 8/19/2023
所以它在确定大小时很糟糕,因为它会转换为字符串?
0赞 Pointy 8/19/2023
@Vishal你的“子数组”是一个普通的 JavaScript 数组。它包含 Uint8Array 实例这一事实不会改变任何内容;Blob 构造过程会将其转换为字符串,因为这就是它所知道的与 Blob 或缓冲区源以外的任何内容有关的全部内容。
0赞 Pointy 8/19/2023
请注意,如果确实使用类型化数组为 Blob 构造函数创建一个数组,则它可以正常工作。
0赞 Vishal 8/19/2023
因此,使用 subArray 计算准确大小很糟糕。我明白了。这会是未来的改进吗?
0赞 Pointy 8/19/2023
@Vishal,它绝对不会试图这样做;它不会递归地下降到您传递它的数据结构中。