命名数组和索引数组之间的区别-JavaScript

时间:2019-06-11 18:29:54

标签: javascript arrays object

在使用数组构造函数并将一些值推入其中以及添加命名值时,会有一些有趣的区别。

let arr = []
arr.push('a')
arr.push('b')
arr.push('c')
arr.foo1 = 'bar1'
arr.foo2 = 'bar2'

arr.forEach和for只能在索引值上进行迭代,而for则用于索引/键值的迭代。

我想我想知道为什么有人会使用它? 可以保证对象和数组的键值对顺序是一件很酷的事情

(不仅是[{key:'value'},{key2:'value2'],还有一些您可以在其上使用of的对象,其顺序将基于该对象的键所处的顺序集合。我知道这是不可能的,只是建议一些可以在对象和数组之间获得的东西)

,但似乎无法迭代键值的顺序,因此不能保证顺序(除非我错了) 这样做似乎是对象和数组之间的混合,但是当您只能以通用方式创建对象或数组时为什么还要混合呢?

2 个答案:

答案 0 :(得分:4)

简短的回答:JS中没有所谓的“命名数组”之类的东西。

JS的数据类型模型基于对象,它们是键/值对容器,而数组是一种特殊的对象,具有用于处理数字键的附加(本机)逻辑。

这样,您可以对对象执行任何操作,也可以对数组执行操作,但您不应该这样做:如果需要命名键,请使用对象。如果您需要具有衍生属性的数字键,例如length和实用程序API,例如push / pop / shift / unshiftforEach,{ {1}}等使用数组。

还请注意,map属性对内存中的实际内存占用没有任何说明:数组根本不像C / Java / etc数组,而是更像矢量/数组列表:它们只是带有数字键/对绑定的JS对象,因此,如果您设置了array [0]然后又设置了array [99],则length将声明“ 100”,而该数字将毫无意义。根本:您的数组在内存中只是一个对象,其中键/值对以 string length为键,而键/值对则以 string 为键 0

这本quora answer很好理解,它基于实际的ECMAScript规范定义对此进行了解释。

答案 1 :(得分:4)

数组是JavaScript对象,类似于您创建的其他对象。 (几乎)JavaScript中的所有内容均从Object继承其原型。

现在,数组的规范使得索引基本上只是专门命名的属性。 a[1]a['1']指向相同的属性。唯一需要注意的是,您必须具有一个length数字属性。在words of ECMAScript language specification中,“数组对象是对特定类的属性名称给予特殊处理的奇异对象”。

现在,forEach被定义为仅循环访问Array实例具有的那些“特殊”属性的函数。它以0开头,以length - 1结尾,并且跳过未定义的值。它没有看其他道具。因此,您只能在数组中获得字段。

for ofiterator-如果您有一个iterable对象,则基本上可以得到其迭代器函数,然后遍历它提供的值。可迭代的数组仅给出那些索引属性名称。您可以阅读更多over at MDN

再次,数组是与其他对象一样的对象,但是我们赋予其某些属性特殊的含义,并且它继承了Array原型中可以处理这些属性的某些功能

但是for in不在乎此对象是否特殊。 它将仅循环提供给您的任何对象的所有属性,包括数组。这就是为什么当您for in循环对象时,您正在循环对象的属性,并且数组索引为包含在其中。

注意:不建议使用for ... in ...例如,在稀疏数组中(例如,在其中设置a [0] = 1,a [10] = 1和保留所有其他未定义的索引),for in只会注销这两个属性。

因此,如果有人给您提供一个具有名为010的属性的对象,您会称之为数组吗?不。另一个不好的事情是,它还会遍历对象的原型,并列出此数组可能已继承的所有对象的属性-并且您可能不希望这样做。