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

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

问题描述


  

可能重复:结果
  是JavaScript数组疏?


我学习的那一刻JavaScript和一直在阅读一些简单的介绍和教程。在注视Array对象我偶然发现了一些细节,这在我看来他们很奇怪,从如C / Java的/斯卡拉/...


所以,让我们假设我们定义数组这样:

  VAR ARR = ['富','酒吧','qux']

我们现在分配

 改编[5] ='巴兹'

这将导致数组中寻找这样的:

  ARR
>> [富,酒吧,qux,不确定的,不确定的,巴兹]

和如预期长度

  arr.length
>> 6


JavaScript的慷慨扩大了我们的阵列所需的长度 - 六 - 和新项目设置为undefined - 除了一个大家实际分配一个值

从一个低水平点,这是可怕的记忆明智的。通常,数组将是一个连续范围内存 - 作出更大的阵列通常包括复制整个数组到一个新的存储位置,大小足够。这是一个非常昂贵的操作。

现在,我不知道这是可能的不可以什么JavaScript引擎在干什么,周围阵列的复制会发疯昂贵,而且存储空间会在所有这些未定义被浪费值。

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


  • 是数组实际上是某种形式的链接列表?

  • 是未定义数组项居然有?

  • 如何昂贵是它与大型阵列的大多是充满了不确定?工作


解决方案

在JavaScript的第一个版本,没有阵列。他们后来被引入作为一个子类的所有对象之母的对象。你可以这样做测试这很容易:

 无功富= [1,2,3,4];
对(在富变种N)
{//检查是否n等于(值和类型)本身,强制转换为数字
    的console.log(N + ===(n)的数字:'字符串')​​;
}

这将再次登录字符串,时间和时间。在内部,所有的数字键转换为字符串。 Length属性只是获取最高的指标,并增加了1到它。而已。当您显示您的数组,对象被重复,并为每个键,同样的规则也适用于任何对象:第一个实例进行扫描,然后原型(S)...因此,如果我们改变我们的codeA位

 无功富= [1,2,3,4];
富[9] = 5;
对(在富变种N)
{
    如果(foo.hasOwnProperty(n))的
    {//检查当前关键是一个数组属性
        的console.log(N + ===(n)的数字:'字符串')​​;
    }
}

您会注意到数组只有5个自己的属性,在未定义键4-8是不确定的,因为当时的实例中发现没有相应的价值,也没有在任何潜在的原型。简而言之:数组是不是真正的数组,但行为相似物体

由于蒂姆说,你的可以的有与未定义的属性数组实例时的该对象中存在:

 无功富= [1,2,不确定的,3];
的console.log(富[2] ===未定义); //真
的console.log(富[99] ===未定义); //真

但同样,是有区别的:

 的console.log((foo.hasOwnProperty('2')及和放大器;富[2] ===未定义)); //真
的console.log((foo.hasOwnProperty('99')及和放大器;富[99] ===未定义)); //假

简而言之,您的三个主要问题:


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


  • 未定义值是不存在的,它们仅仅是当JS扫描的对象和原型,找不到默认返回值是你重新寻找:对不起,你问我是在我的书未定义的是它说什么


  • 使用基本上未定义阵列工作不影响对象本身的大小,但在访问一个未定义关键可能是非常的非常的略微慢,因为原型具有要被扫描,也

更新:

在Ecma的STD :


  

15.4数组对象

  Array对象给予特殊处理某一类的属性名称。属性名称P(在的形式
  字符串值)是一个数组索引,当且仅当的ToString(ToUint32(P))等于P和ToUint32(P)为不等于
  2 ^ 32
  1。一个属性,其属性名是数组索引也被称为一个元素。每个数组对象都有一个
  length属性的值始终是一个非负整数小于2 ^ 32。长度的值
  属性数值上比每个属性的名字是一个数组索引的名称越大;每当
  创建或更改Array对象的属性,其他属性调整为要保持这个
  不变的。具体来说,只要属性添加名为数组索引,长度属性
  改变,如果需要的话,为比数组索引的数值多一个;每当长度
  属性被改变时,每一个属性,它的名称是一个数组索引,其值不小于新小
  长度被自动删除。此约束仅适用于Array对象的自己的属性,是
  通过可从它的原型继承长度或数组索引属性不受影响。


  
  

的目的,O被认为是稀疏如果下列算法返回真:

  1.让LEN是调用的O的[[Get]]内部方法与参数长度的结果。

  2.对于每个整数i的范围0≤i
  
    一个。让ELEM是参数调用的O的[[GetOwnProperty]]内部方法的结果
         的ToString(i)中。
  
      b。如果ELEM是不确定的,返回true。

  3.返回假的。


Possible Duplicate:
Are Javascript arrays sparse?

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']

We now assign

arr[5] = 'baz'

which results in our array looking like this:

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

And the length is as expected

arr.length
>> 6


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.

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?

  • Are arrays actually some sort linked lists?
  • Are the 'undefined' array items actually there?
  • How expensive is it to work with large arrays that are mostly filled with 'undefined'?

解决方案

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');
}

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');
    }
}

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.

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

But again, there is a difference:

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

RECAP, your three main questions:

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

  • 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.

  • Working with largely undefined arrays doesn't affect the size of the object itself, but accessing an undefined key might be very, very marginally slower, because the prototypes have to be scanned, too.

Update:

Just quoting the Ecma std:

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.

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的数组的内存管理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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