JavaScript Array 的内存管理 [英] Memory management of JavaScript Array

查看:26
本文介绍了JavaScript Array 的内存管理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能的重复:
Javascript 数组是稀疏的吗?

我目前正在学习 JavaScript,并且一直在阅读一些简单的介绍和教程.在查看 Array 对象时,我偶然发现了一些细节,这些细节让我觉得很奇怪,来自其他语言,如 C/Java/Scala/...

I am learning JavaScript at the moment and have been reading some simple introductions and tutorials. While looking at the Array object I stumbled upon some details, which strike me as very odd, coming from other languages like C/Java/Scala/...

假设我们这样定义一个数组:

So lets assume we define an array as such:

var arr = ['foo','bar','qux']

我们现在分配

arr[5] = 'baz'

这导致我们的数组看起来像这样:

which results in our array looking like this:

arr
>> ["foo", "bar", "qux", undefined, undefined, "baz"]

长度符合预期

arr.length
>> 6

<小时>

JavaScript 已将我们的数组扩展到所需的长度 - 六 - 并且新项目设置为未定义 - 除了我们实际为其赋值的项目.


JavaScript has kindly expanded our array to the needed length - six - and the new items are set to undefined - except for the one we actually assigned a value to.

从低层次的角度来看,这在记忆方面是可怕的.通常,数组是内存中的一个连续范围 - 使数组更大通常涉及将整个数组复制到新的内存位置,大小足够.这是一项非常昂贵的操作.

From a low level point of view this is horrible memory-wise. Typically an array would be a continuous range in memory - making an array bigger generally involves copying the whole array to a new memory location, sufficient in size. This is a very costly operation.

现在,我确实意识到这可能不是 JavaScript 引擎正在做的事情,因为在数组周围复制将非常昂贵,并且内存空间将浪费在所有这些未定义"上价值.

Now, I do realize that this is likely not what JavaScript engines are doing, as copying around arrays would be crazy expensive and the memory space would be wasted on all these 'undefined' values.

谁能告诉我门后到底发生了什么?

Can someone tell me what actually happens behind the door?

  • 数组实际上是某种类型的链表吗?
  • 未定义"数组项实际上存在吗?
  • 处理主要填充未定义"的大型数组的成本有多大?

推荐答案

在 JavaScript 的第一个版本中,没有数组.它们后来被引入为所有对象之母"的子类:Object.你可以很容易地通过这样做来测试:

In the first version of JavaScript, there were no arrays. They were later introduced as a sub-class of that "mother of all objects": Object. You can test this quite easily by doing this:

var foo = [1,2,3,4];
for (var n in foo)
{//check if n is equal (value and type) to itself, coerced to a number
    console.log(n === +(n) ? 'Number' : 'String');
}

这将一次又一次地记录String.在内部,所有数字键都转换为字符串.Length 属性仅获取最高索引,并将其加 1.而已.当你显示你的数组时,对象被迭代,对于每个键,同样的规则适用于任何对象:首先扫描实例,然后是原型......所以如果我们稍微改变我们的代码:

This will log String, time and time again. Internally, all numeric keys are converted to strings. The Length property merely fetches the highest index, and adds 1 to it. Nothing more. When you display your array, the object is iterated, and for each key, the same rules apply as for any object: first the instance is scanned, then the prototype(s)... so if we alter our code a bit:

var foo = [1,2,3,4];
foo[9] = 5;
for (var n in foo)
{
    if (foo.hasOwnProperty(n))
    {//check if current key is an array property
        console.log(n === +(n) ? 'Number' : 'String');
    }
}

你会注意到数组只有 5 个自己的属性,undefined 键 4-8 是未定义的,因为在实例中没有找到相应的值,也没有在任何底层原型中.简而言之:数组并不是真正的数组,而是行为相似的对象.

You'll notice the array only has 5 own properties, the undefined keys 4-8 are undefined, because there was no corresponding value found within the instance, nor in any of the underlying prototypes. In short: Arrays aren't really arrays, but objects that behave similarly.

正如 Tim 所说,您可以拥有一个数组实例,该实例具有确实存在于该对象中的未定义属性:

As Tim remarked, you can have an array instance with an undefined property that does exist within that object:

var foo = [1,2,undefined,3];
console.log(foo[2] === undefined);//true
console.log(foo[99] === undefined);//true

但还是有区别的:

console.log((foo.hasOwnProperty('2') && foo[2] === undefined));//true
console.log((foo.hasOwnProperty('99') && foo[99] === undefined));//false

回顾一下,您的三个主要问题:

  • 数组是对象,允许你用数字实例引用它们的属性

  • Arrays are objects, that allow you to reference their properties with numeric instances

undefined 值不存在,它们只是当 JS 扫描对象和原型并且找不到您要查找的内容时的默认返回值:对不起,你问我的问题在我的书中没有定义."就是它所说的.

The undefined values are not there, they're merely the default return value when JS scans an object and the prototypes and can't find what you're looking for: "Sorry, what you ask me is undefined in my book." is what it says.

更新:

只需引用 Ecma 标准:

15.4 数组对象
数组对象对特定类别的属性名称进行特殊处理.属性名称 P(形式为 a字符串值) 是数组索引当且仅当 ToString(ToUint32(P)) 等于 P 且 ToUint32(P) 不等于2^32-1.属性名称为数组索引的属性也称为元素.每个 Array 对象都有一个length 属性,其值始终是小于 2^32 的非负整数.长度值属性在数字上大于名称为数组索引的每个属性的名称;每当一个创建或更改 Array 对象的属性,根据需要调整其他属性以保持此不变的.具体来说,每当添加名称为数组索引的属性时,长度属性为如有必要,更改为比该数组索引的数值大 1;每当长度属性被更改,名称为数组索引的每个属性的值不小于新的长度自动删除.此约束仅适用于 Array 对象的自身属性,并且是不受可能从其原型继承的长度或数组索引属性的影响.

15.4 Array Objects
Array objects give special treatment to a certain class of property names. A property name P (in the form of a String value) is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 2^32 1. A property whose property name is an array index is also called an element. Every Array object has a length property whose value is always a nonnegative integer less than 2^32. The value of the length property is numerically greater than the name of every property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. Specifically, whenever a property is added whose name is an array index, the length property is changed, if necessary, to be one more than the numeric value of that array index; and whenever the length property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted. This constraint applies only to own properties of an Array object and is unaffected by length or array index properties that may be inherited from its prototypes.

如果以下算法返回真,则称对象 O 是稀疏的:
1.令len为参数为length"的O的[[Get]]内部方法调用的结果.
2.对于0≤i范围内的每个整数i
   a.令 elem 为带参数调用 O 的 [[GetOwnProperty]] 内部方法的结果      ToString(i).
    b.如果 elem 未定义,则返回 true.
3.返回false.

An object, O, is said to be sparse if the following algorithm returns true:
1. Let len be the result of calling the [[Get]] internal method of O with argument "length".
2. For each integer i in the range 0≤i
    a. Let elem be the result of calling the [[GetOwnProperty]] internal method of O with argument        ToString(i).
     b. If elem is undefined, return true.
3. Return false.

这篇关于JavaScript Array 的内存管理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆