一尘不染

物理内存中的JavaScript数组如何表示?

javascript

据我了解,我可以将混合数据存储在JavaScript数组中,也可以将数组中的任何元素更改为其他类型。解释器如何跟踪任何元素在物理内存中的位置。另外,如果将元素更改为更大的数据类型,那么如何防止下一个元素中的数据被覆盖。

我假设数组仅存储对实际对象的引用,并且将基元放置在数组中时将其包装在幕后。

假设是这种情况,如果我对原始变量有不同的句柄并更改存储在数组中的值是否保持同步?

我知道我可能已经回答了我自己的问题,但是我不确定,因此也找不到任何信息。


阅读 403

收藏
2020-05-01

共1个答案

一尘不染

通常,数组分配固定长度的连续内存块。但是,在Javascript中,数组是具有特殊构造函数和访问器方法的Object类型。

意思是说:

var arr = new Array(100000);

不分配任何内存!实际上,它只是在数组中设置length属性的值。构造数组时,不需要声明大小,因为它们会自动增长。因此,您应该改用以下方法:

var arr = [];

Javascript中的数组是稀疏的,这意味着并非数组中的所有元素都可能包含数据。换句话说,只有实际包含数据的元素存在于数组中。这减少了阵列使用的内存量。这些值是通过键而不是偏移量定位的。它们只是一种便捷的方法,并不打算用于复杂的数值分析。

Javascript中的数组未输入类型,因此元素的值可以是对象,字符串,数字,布尔值,函数或数组。数组和对象之间的主要区别是length属性,该属性的值大于数组中最大的整数键。

例如:

您可以创建一个空数组,并在索引0和索引99处添加两个元素。长度为100,但数组中的元素数为2。

var arr = [];
arr[0] = 0;
arr[99] = {name: "John"};
console.log(arr.length); // prints 100
arr; // prints something like [0, undefined × 98, Object { name: "John"}]

要直接回答您的问题:

问:据我了解,我可以将混合数据存储在JavaScript数组中,也可以将数组中的任何元素更改为其他类型。解释器如何跟踪任何元素在物理内存中的位置?另外,如果将元素更改为更大的数据类型,如何防止下一个元素中的数据覆盖?

答:如果您已经阅读了上面的评论,那么您现在可能已经知道了。在Javascript中,数组是Hashtable
Object类型,因此解释器不需要跟踪物理内存,并且更改元素的值不会影响其他元素,因为它们不会存储在连续的内存块中。

-

问:我假设数组仅存储对实际对象的引用,而基元放置在数组中时会被包装在幕后。假设是这种情况,如果我对原始变量有不同的句柄并更改存储在数组中的值是否保持同步?

答:不,基元没有包装。更改分配给数组的基元不会更改数组中的值,因为它们是按值存储的。另一方面,对象是通过引用存储的,因此更改对象值将反映该数组中的更改。

您可以尝试以下示例:

var arr = [];
var obj = { name: "John" };
var isBool = true;

arr.push(obj);
arr[1] = isBool;

console.log(arr[0]); // print obj.name
console.log(arr[1]); // print true

obj.age = 40;        // add age to obj
isBool = false;      // change value for isBool

console.log(arr[0]); // value here will contain age
console.log(arr[1]); // value here will still be true

另外,请注意,当您通过以下两种方式初始化数组时,它具有不同的行为:

var arr = new Array(100);
console.log(arr.length);        // prints 100
console.log(arr);               // prints []

var arr2 = new Array(100, 200);
console.log(arr2.length);       // prints 2
console.log(arr2);              // prints [100, 200]

如果要使用Javascript数组作为连续的内存块,则应考虑使用TypedArray。TypedArray允许您将内存块分配为字节数组,并更有效地访问原始二进制数据。

您可以通过阅读[ECMA-262规范版本5.1)来了解有关Javascript复杂性的更多信息。

2020-05-01