通常,数组分配一个固定长度的连续内存块。但是,在 Javascript 中,数组是具有特殊构造函数和访问器方法的 Object 类型。
也就是说,像这样的语句:
var arr = new Array(100000);
不分配任何内存!实际上,它只是简单地设置数组中长度属性的值。当你构造一个数组时,你不需要声明一个大小,因为它们会自动增长。所以,你应该改用这个:
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 数组中,也可以将数组中的任何元素更改为其他类型。解释器如何跟踪任何元素在物理内存中的位置?另外,如果我将元素更改为更大的数据类型,如何防止覆盖下一个元素中的数据?
A.如果您已经阅读了我上面的 cmets,您现在可能已经知道这一点。在 Javascript 中,数组是一种 Hashtable 对象类型,因此解释器不需要跟踪物理内存,并且更改元素的值不会影响其他元素,因为它们没有存储在连续的内存块中。
--
问。我假设数组只存储对实际对象的引用,当放置在数组中时,原语被包装在幕后。假设是这种情况,如果我对原始变量有不同的句柄并更改存储在数组中的值是否保持同步?
A.不,原语没有被包装。更改分配给数组的原语不会更改数组中的值,因为它们是按值存储的。另一方面,对象是通过引用存储的,因此更改对象值将反映该数组中的更改。
您可以尝试以下示例:
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 spec (ver 5.1) 了解更多关于 Javascript 的复杂性。