javascript 数组长度和未定义索引

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31235599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 13:30:38  来源:igfitidea点击:

Array length and undefined indexes

javascriptarrays

提问by Ahmet Can Güven

I just want to understand how Javascript arrays work but I have a complicated problem here.

我只是想了解 Javascript 数组是如何工作的,但我在这里遇到了一个复杂的问题。

First I created my array:

首先我创建了我的数组:

var arr = [];

And set some elements in it:

并在其中设置一些元素:

arr[5] = "a thing";
arr[2] = undefined;

I thought that I should have an array of size 2, because I only have two objects at 2 specific indexes. So I tested it with the .lengthproperty of arrays:

我认为我应该有一个大小为 2 的数组,因为我在 2 个特定索引处只有两个对象。所以我用.length数组的属性测试了它:

document.write(arr.length + "<br>");

The result, interestingly, is 6. But it must contain two items. How can its size be 6? It is probably related with the latest index that I used, here arr[5] = "a thing";

有趣的是,结果是 6。但它必须包含两个项目。它的大小怎么可能是6?它可能与我使用的最新索引有关,这里arr[5] = "a thing";

I then tried to loop over it:

然后我试图循环它:

var size = 0;
for(var x in arr){
 size++;   
}

And the sizevariable is now 2. So, what I learned from this: if I use a for inloop, I will calculate how many properties are in it, not its last index.

size可变现在是2。所以,我从中学到:如果我使用一个for in循环,我会计算有多少性能是它,而不是它的最后一个索引。

But if I try to document.write(arr[4])(which is not set yet), it writes undefined.

但是如果我尝试document.write(arr[4])(尚未设置),它会写undefined.

So why is arr[2]counted in the for..inloop, but not arr[4]?

那么为什么arr[2]for..in循环中被计数,而不是arr[4]

Let me answer my question: what I was thinking about typeof undefined == undefinedwhich is amazingly true. But this is JavaScript, we need to play with it using his own rules :)

让我回答我的问题:我在想什么typeof undefined == undefined,这是非常正确的。但这是 JavaScript,我们需要使用他自己的规则来玩它:)

jsFiddleand snippet below.

jsFiddle和下面的代码片段。

var arr = [];

arr[5] = "a thing";
arr[2] = undefined;
document.write(arr.length + "<br>");

var size = 0;
for(var x in arr){
 size++;   
}

document.write(size + "<br>");

document.write(arr[4] + "<br>");

采纳答案by thefourtheye

Note:Array indexes are nothing but properties of Array objects.

注意:数组索引只不过是数组对象的属性。

Quoting MDN's Relationship between lengthand numerical propertiessection,

引用 MDN 的与数值属性之间length关系部分,

When setting a property on a JavaScript array when the property is a valid array index and that index is outside the current bounds of the array, the engine will update the array's lengthproperty accordingly.

在 JavaScript 数组上设置属性时,如果该属性是有效的数组索引并且该索引超出数组的当前边界,引擎将相应地更新数组的length属性。

Quoting ECMA Script 5 Specification of Array Objects,

引用 ECMA Script 5 Specification of Array Objects

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

每当添加名称为数组索引的属性时,如果需要,长度属性将更改为比该数组索引的数值大 1;每当更改长度属性时,名称为数组索引且值不小于新长度的每个属性都会自动删除

So, when you set a value at index 5, JavaScript engine adjusts the length of the Array to 6.

因此,当您在 index 处设置一个值时5,JavaScript 引擎会将 Array 的长度调整为6



Quoting ECMA Script 5 Specification of Array Objects,

引用 ECMA Script 5 Specification of Array Objects

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 Pand ToUint32(P)is not equal to 232?1.

属性名称P(以字符串值的形式)是数组索引,当且仅当ToString(ToUint32(P))等于PToUint32(P)不等于 2 32?1。

So, in your case 2and 4are valid indexes but only 2is defined in the array. You can confirm that like this

因此,在您的情况下,24是有效索引,但仅2在数组中定义。你可以像这样确认

arr.hasOwnProperty(2)

The other indexes are not defined in the array yet. So, your array object is called a sparse array object.

其他索引尚未在数组中定义。因此,您的数组对象称为稀疏数组对象

So why arr[2] is counted in for..in loop and not arr[4] is not counted?

那么为什么 arr[2] 被计入 for..in 循环而不是 arr[4] 不计入?

The for..inenumerates all the valid enumerable properties of the object. In your case, since only 2is a valid property in the array, it will be counted.

for..in枚举所有对象的有效枚举的属性。在您的情况下,由于仅2是数组中的有效属性,因此将对其进行计数。

But, when you print arr[4], it prints undefined, because JavaScript will return undefined, if you try to access a property which is not defined in an object. For example,

但是,当您打印时arr[4],它会打印undefined,因为undefined如果您尝试访问未在对象中定义的属性,JavaScript 将返回。例如,

console.log({}['name']);
// undefined

Similarly, since 4is not yet defined in the arr, undefinedis returned.

同样,由于4尚未在 中定义arrundefined则返回。



While we are on this subject, you might want to read these answers as well,

当我们讨论这个主题时,您可能也想阅读这些答案,

回答by Ry-

There's a difference between a property that has the value undefinedand a property that doesn't exist, illustrated here using the inoperator:

具有值undefined的属性和不存在的属性之间存在差异,此处使用in运算符进行说明:

var obj = {
    one: undefined
};

console.log(obj.one === undefined); // true
console.log(obj.two === undefined); // true

console.log('one' in obj); // true
console.log('two' in obj); // false

When you try to get the value of a property that doesn't exist, you still get undefined, but that doesn't make it exist.

当您尝试获取不存在的属性的值时,您仍然会获取undefined,但这并不使它存在。

Finally, to explain the behaviour you see: a for inloop will only loop over keys where that key is inthe object (and is enumerable).

最后,解释一下你看到的行为:一个for in循环只会在那个键是in对象(并且是可枚举的)的键上循环。

length, meanwhile, is just adjusted to be one more than whatever index you assign if that index is greater than or equal to the current length.

length同时,如果该索引大于或等于当前长度,则只是将其调整为比您分配的任何索引多一。

回答by guest271314

To remove undefinedvalues from array , try utilizing .filter()

要从undefined数组中删除值,请尝试使用.filter()

var arr = [];
arr[5] = "a thing";
arr[2] = undefined;
arr = arr.filter(Boolean);
document.write(arr.length);

回答by Orlando Paredes Hamsho

It all comes down the idea of how space is handled by machines. Let's start with the simplest idea of:

这一切都归结于机器如何处理空间的想法。让我们从最简单的想法开始:

var arr =[];

This in turn creates a locationwhere you can now store information. As @Mike 'Pomax' Kamermans pointed out: This location is a special javascript object that in turn functions as a collection of keys and values, like so:

这反过来又会创建一个位置,您现在可以在其中存储信息。正如@Mike 'Pomax' Kamermans 指出的那样:这个位置是一个特殊的 javascript 对象,它又作为键和值的集合起作用,如下所示:

arr[key] = value;

Now moving on through your code:

现在继续浏览您的代码:

arr[5] = "a thing";

The machine now is understanding that you are creating something in the (giving value to the) 6th position/5th key(as array's first position is 0). So you wind up with something that looks like this:

机器现在知道您正在(为)第 6 个位置/第 5 个键(因为数组的第一个位置为 0)创建一些东西(赋予值)。所以你最终会得到如下所示的东西:

arr[,,,,,"a thing"];

Those commas represent empty positions (elisions as @RobG pointed out) in your array.

这些逗号代表数组中的空位置(@RobG 指出的省略)。

Same thing happens when you declare:

当您声明时会发生同样的事情:

arr[2] = undefined;
arr[,,undefined,,,"a thing"];

So when you're iterating inside an array using "for var in" you're checking for each one of the spaces in this array that are populated, so in turn 2.

因此,当您使用“for var in”在数组内部进行迭代时,您正在检查该数组中已填充的每个空格,因此依次为 2。

As a difference, when you check for the length of the array, you're looking to see how many spaces to store information existinside the array, which in turn is 6.

不同的是,当您检查数组的长度时,您会查看数组中存在多少个用于存储信息的空间,而后者又是 6 个。

Finally, javascript interprets empty room in an array as unidentified values, which is the reason arr[4] is being outputted as such.

最后,javascript 将数组中的空房间解释为未识别的值,这就是 arr[4] 被这样输出的原因。

Hope that answered your question.

希望回答了你的问题。

回答by Giuseppe Pes

JavaScript arrays, at least in the first version, were plain object with a lengthproperty. Most of the weird behaviour you experienced is a consequence of this.

JavaScript 数组,至少在第一个版本中,是带有length属性的普通对象。您所经历的大多数奇怪行为都是由此造成的。

Result interesting, it is 6. But it must contain two data, how its size can be 6? It is probably related with the latest index that I used here arr[5] = "a thing";

结果很有趣,它是6。但它必须包含两个数据,它的大小怎么可能是6?大概和我这里用的最新索引有关 arr[5] = "a thing";

It results in 6because the lengthis always 1 higher than the highest index, even if there are actually fewer items in the array.

这导致6,因为length始终为1比最高指数走高,即使有数组中的实际项目较少。

o why arr[2] is counted in for..in loop and not arr[4] is not counted?

o 为什么 arr[2] 计入 for..in 循环而不计入 arr[4] ?

because when you are doing:

因为当你在做:

arr[2] = undefined;

arr[2] = undefined;

You are actually adding a key called 2to the array object. As result, the value arr[2]is counted in the for inloop, while the a[4]is ignored.

您实际上是在添加一个调用2数组对象的键。结果,该值arr[2]for in循环中被计数,而a[4]被忽略。

回答by Catalyst

The assignment sets the property of the array, so that when you do the for var i instyle for loop, you only see properties that have been set (even if you set them to be undefined). When you assign a new integery property such as arr[6]the array modifies the length of the array to be 7. The memory underlying the array may or may not be reallocated accordingly, but it will be there for you when you go to use it - unless your system is out of memory.

赋值设置了数组的属性,因此当您执行for var i in样式 for 循环时,您只能看到已设置的属性(即使您将它们设置为未定义)。当您分配一个新的整数属性(例如arr[6]数组)时,会将数组的长度修改为 7。数组底层的内存可能会也可能不会相应地重新分配,但是当您使用它时它会在那里 - 除非您系统内存不足。

Edited according to RobG's comment about what ECMA-262 says.

根据 RobG 对 ECMA-262 所说内容的评论进行编辑。