gpt4 book ai didi

javascript - JavaScript Array 的内存管理

转载 作者:IT王子 更新时间:2023-10-28 23:30:54 25 4
gpt4 key购买 nike

Possible Duplicate:
Are Javascript arrays sparse?

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


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

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

我们现在分配

arr[5] = 'baz'

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

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

而且长度符合预期

arr.length
>> 6

JavaScript 已经将我们的数组扩展到所需的长度 - 六 - 并且新项目设置为未定义 - 除了我们实际分配值的那个。

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

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

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

  • 数组实际上是某种排序链表吗?
  • “未定义”数组项是否真的存在?
  • 处理大部分都充满“未定义”的大型数组的成本有多高?

最佳答案

在 JavaScript 的第一个版本中,没有数组。它们后来作为“所有对象之母”的子类引入:Object。您可以通过以下方式轻松测试:

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。而已。当你显示你的数组时,对象会被迭代,并且对于每个键,同样的规则适用于任何对象:首先扫描实例,然后是原型(prototype)......所以如果我们稍微改变一下代码:

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 是未定义的,因为在实例中没有找到对应的值,在任何底层原型(prototype)中也没有。简而言之:数组并不是真正的数组,而是行为相似的对象。

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

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

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

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

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

  • 使用大部分未定义的数组不会影响对象本身的大小,但访问未定义的键可能会非常、非常稍微慢一些,因为还必须扫描原型(prototype)。

更新:

只需 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 - JavaScript Array 的内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12640216/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com