Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript数组如何在物理内存中表示?_Javascript_Arrays_Dynamic_Weakly Typed - Fatal编程技术网

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

JavaScript数组如何在物理内存中表示?,javascript,arrays,dynamic,weakly-typed,Javascript,Arrays,Dynamic,Weakly Typed,据我所知,我可以在JavaScript数组中存储混合数据,也可以将数组中的任何元素更改为其他类型。解释器如何跟踪任何元素在物理内存中的位置。另外,如果我将一个元素更改为更大的数据类型,如何防止下一个元素中的数据被覆盖 我假设数组只存储对实际对象的引用,并且在数组中放置原语时,原语被包装在幕后 假设是这种情况,如果我对原语变量有不同的句柄,并且更改了存储在数组中的值,那么是否保持了同步性 我知道我可能已经回答了我自己的问题,但我不确定,我也找不到关于这件事的任何信息 通常,数组分配固定长度的连续内

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

我假设数组只存储对实际对象的引用,并且在数组中放置原语时,原语被包装在幕后

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


我知道我可能已经回答了我自己的问题,但我不确定,我也找不到关于这件事的任何信息

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

也就是说,像这样的陈述:

var arr = new Array(100000);
不分配任何内存!实际上,它只是设置数组中length属性的值。构造数组时,不需要在数组自动增长时声明大小。因此,您应该使用此选项:

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

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

例如:

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
您可以创建一个空数组,并在索引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"}]
直接回答您的问题:

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

答:如果你读过我上面的评论,你现在可能已经知道了这一点。在Javascript中,数组是哈希表对象类型,因此解释器不需要跟踪物理内存,并且更改元素的值不会影响其他元素,因为它们不存储在连续的内存块中

--

我假设数组只存储对实际对象的引用,并且在数组中放置原语时,原语被包装在幕后。假设是这种情况,如果我对原语变量有不同的句柄,并且更改了存储在数组中的值,那么是否保持了同步性

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

以下是一个您可以尝试的示例:

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允许您将内存块分配为字节数组,并更有效地访问原始二进制数据


您可以通过阅读来了解Javascript的复杂性。

这里有一些值得思考的东西。我让一些JavaScript引擎实现了这一点

测试用例创建了两个数组,每个数组包含一百万个元素。
a
数组只包含数字;
b
数组包含相同的数字,但第一个元素是对象:

var a = [ 0 ], b = [ { valueOf: function() { return 0; } } ];
for( var i = 1;  i < 1000000;  ++i ) {
    a[i] = b[i] = i;
}
慢速阵列:

var x = 0;
for( var i = 0;  i < 1000000;  ++i ) {
    x += b[i];
}
var x=0;
对于(变量i=0;i<1000000;++i){
x+=b[i];
}
从jsperf中的测试结果可以看出,在Chrome中,数字数组大约快5倍,在Firefox中,数字数组大约快10倍,在IE中大约快2倍


这并不能直接揭示用于阵列的内部结构,但它很好地表明了这两种结构之间的差异。

公认的答案是

[阵列构造]不分配任何内存


这不一定是真的。将数组作为无序的键值对存储在对象中是非常低效的,因为每次查找都是一次搜索。即使对条目进行了排序,它仍然会分配比需要更多的内存。因此,许多引擎以几种不同的方式表示阵列,以保护内存并优化性能。这也可以在Michael Geary的示例中看到,ony包含数字的数组得到了优化()。有时,如果基础表示具有固定的大小且无法轻松缩放(例如数组列表),引擎可能会决定为新创建的数组分配一些空插槽。

不同的JavaScript实现可能有不同的方法。您不能修改原语。分配数组元素永远不会改变其他变量或数组。(如果数组是另一个数组(或多个其他数组)的元素,则可以通过其他数组看到更改,但您永远不会,比如说,将
x=3
,分配到某个数组的某个位置,然后突然看到
x==4
)这就是您所说的JS中的数组与其他语言中的数组不同的意思。他们没有那些来自于连续分区的优化