JavaScript中的数组建立

数组是一个包含了对象或原始类型的有序集合。很难想象一个不使用数组的程序会是什么样。javascript

如下是几种操做数组的方式:java

  1. 初始化数组并设置初始值web

  2. 经过索引访问数组元素swift

  3. 添加新元素数组

  4. 删除现有元素浏览器

本文涵盖了数组的初始化以及设置初始值的操做。在JavaScript中要作到这一点的基本方法是使用数组字面量,例如[1, 5, 8]或是数组构造器new Array (1, 5, 8)bash

除了手动枚举以外,JavaScript还提供了更有趣更直接的数组建立方式。让我一块儿看看在JavaScript中初始化数组的通常场景和高级场景吧。函数

1. 数组字面量

数组字面量由一组包裹在方括号[ ]之间的逗号分隔的元素element1, element2, ..., elementN组成。ui

让咱们看几个数组字面量的例子:spa

在JS Bin中查看

let numbers = [1, 5, 7, 8]; let planets = ['Earth', 'Mercury', 'Jupiter'];

数组字面量能够包含任意类型的元素,包括nullundefined, 原始类型以及对象:

在JS Bin中查看

let mixed = [1, 'Earth', null, NaN, undefined, ['Mars']];

1.1 数组字面量中的逗号

逗号,用来分隔数组字面量中的元素。基于逗号的位置或是逗号之间元素的缺失的状况,不一样结构的数组会被建立。

让咱们详细看一看现有的三种状况。

第一种状况:普通的数组字面量

一般状况是在任何一对逗号之间都有一个元素而且数组字面量不以逗号开始或结尾。这是推荐的使用逗号分隔手动初始化数组的方式:

在JS Bin中查看

let items = ['first', 'second', 'third']; items; // => ['first', 'second', 'third']

items是由2个逗号分隔的3个元素建立的。

在这个例子中item是一个密集数组,由于它的元素有着连续的索引(或者简单来讲数组中没有空洞)。

大多数时候,你会使用这种方式初始化数组。

第二种状况: 在数组末尾的一个无用逗号

第二种状况和第一种状况相似,只不过在最后一个逗号以后没有指定元素。这种状况中,最后一个逗号会被JavaScript忽略:

在JS Bin中查看

let items = ['first', 'second', 'third', ]; items; // => ['first', 'second', 'third']

在元素'third'以后指定的一个逗号,它是数组中的最后一个逗号而且在那以后没有任何元素。这个末尾的逗号是无用的,意味着它对新建立的数组没有任何影响。

这种状况下JavaScript也会建立一个密集数组。

第三种状况: 逗号之间没有元素

第三种状况发生在当一对逗号之间没有指定元素或是数组字面量以一个逗号开始时。

这会建立一个稀疏数组:一个其元素索引不连续的集合(换句话说数组中存在空洞)。

下面的数组字面量以逗号开始,建立了一个稀疏数组:

在JS Bin中查看

let items = [, 'first', 'second', 'third']; items; // => [<1 empty slot>, 'first', 'second', 'third'] items[0]; // => undefined items[1]; // => 'first' items.length; // => 4

数组字面量[, ...]以逗号开始。结果是items是一个稀疏数组,在索引0的位置是一个空slot。访问空slot items[0]会获得undefined

区分一个空slot和一个值是undefined的元素是很重要的。经过索引访问这种类型的元素时都会获得undefined,这使得区分它们变得很棘手。

空slot意味着数组在某个索引位置上没有元素(index in array返回false),这与一个值是undefined的元素(index in array返回true)是不一样的。

须要注意的是空slot在Firefox的控制台会被显示为<1 empty slot>,这是展现空slot的正确方法。Chrome的控制台会展现undefined x 1。其它浏览器的控制台只会简单的展现undefined

当数组字面量的两个逗号之间没有元素时也会建立一个稀疏数组:

在JS Bin中查看

let items = ['first', , 'second', 'third']; items; // => ['first', <1 empty slot> ,'second', 'third'] items[0]; // => 'first' items[1]; // => undefined items.length; // => 4

数组字面量包含了中间没有元素的逗号:[... , , ...]。这样item成了一个索引1处是一个空slot的稀疏数组。访问空slot items[1]会获得undefined

一般你应该避免这种会建立稀疏数组的使用方式。同时你也应该尽量的不去操做稀疏数组。

在一个数组字面量中删除或是添加元素时你可能会在不经意间建立一个稀疏数组。所以在修改以后切记仔细检查。

1.2 spread运算符带来的改善

ECMAScript 6中引入的spread运算符改善了使用其它数组中的元素初始新数组这一操做。

在不少场景下spread运算符均可以使数组建立变得更简单。方法就是在数组字面量中把...做为源数组的前缀,而后源数组中的元素就被包括到新建立的数组中了。就这么简单。

下面的数组字面量在建立时使用了spread运算符:

在JS Bin中查看

let source = ['second', 'third']; let items = ['first', ...source]; items; // => ['first', 'second', 'third']

数组字面量['First', ...source]表示'First'会被做为数组中的第一个元素。剩余的元素则是经过spread运算符从source数组取得。

常规的元素枚举方式能够和spread运算符能够不受限制的组合在一块儿。

在JS Bin中查看

let odds = [1, 3, 5]; let evens = [4, 6]; let zero = 0; let negative = -1; let items = [...odds, zero, ...evens, negative]; items; // => [1, 3, 5, 0, 4, 6, -1]

建立items时使用一个组合了普通变量zeronegative以及前置spread运算符的源数组...odds...evens的集合。

因为spread运算符接收的是普通的可迭代对象(数组默认就是可迭代的),这使得自定义的初始化成为可能。

一个生成器函数也会返回一个可迭代的生成器对象,所以你能够利用生成器的灵活性来建立数组。

让咱们建立一个第一个参数表明元素值第二个参数表明元素数量的生成器函数。而后使用它和spread运算符以及数组字面量来初始化新数组:

在JS Bin中查看

function* elements(element, length) { let index = 0; while (length > index++) { yield element; } } [...elements(0, 5)]; // => [0, 0, 0, 0, 0] [...elements('hi', 2)]; // => ['hi', 'hi']

每次执行elements(element, length)时都会建立一个生成器对象。spread运算符会利用该生成器对象来初始化数组。

[...elements(0, 5)]会建立一个有5个0的数组。而[...elements('hi', 2)]会建立一个有两个字符串'h1'的数组。

2. 数组构造器

JavaScript中的数组是一个对象。和任何对象同样,它有一个能够用来建立新实例的构造器函数Array。让咱们看一个例子:

在JS Bin中查看

// 构造器调用 let arrayConstr = new Array(1, 5); arrayConstr; // => [1, 5] typeof arrayConstr; // => 'object' arrayConstr.constructor === Array; // => true // 数组字面量 let arrayLiteral = [1, 5]; arrayLiteral; // => [1, 5] typeof arrayLiteral; // => 'object' arrayLiteral.constructor === Array; // => true

arrayConstrarrayLiteral都是数组实例,它们的构造器都是Array。对象arrayConstr是经过构造器调用建立的:new Array(1, 5)

你也能够像调用普通函数那样经过Array来建立数组实例:Array(1, 5)

你应该更倾向于使用字面量[item1, item2, ..., itemN]而不是构造器new Array(item1, item2, ..., itemN)来建立数组。主要缘由是数组字面量的写法更短,更简单。还有一个缘由就是数组构造器在第一个参数是不一样类型的值时,产生的怪异行为。

让咱们看看Array使如何根据第一个参数的类型以及参数的个数来建立数组实例的吧。

2.1 数值类型的参数下建立稀疏数组

当数组构造器new Array(numberArg)以一个单一的数值类型的参数调用时,JavaScript会建立一个带有参数指定的个数的空slot的稀疏数组。

看一个例子:

在JS Bin中查看

let items = new Array(3); items; // => [<3 empty slots>] items.length; // => 3

new Array(3)是一个带有单一参数3的构造器调用。一个长度为3的稀疏数组items被建立了,但实际上它并不包含任何元素而只是有几个空slot。

这种建立数组的方式自己并无什么价值。然而把它和一些静态方法组合起来用于建立指定长度的数组并填充生成的元素时倒是有用的。

2.2 枚举元素

若是调用Array构造器时传入了一个参数列表而不是单个数字,那么这些参数就会成为数组的元素。

这种方式和数组字面量的方式几乎同样,只不过是在一个构造器调用中而已。

下面的例子建立了一个数组:

let items = new Array('first', 'second', 'third'); items; // => ['first', 'second', 'third']

new Array('first', 'second', 'third')使用参数中的元素建立了一个数组。

因为spread运算符的灵活性,在构造器调用中使用来自其它数组的元素也是可行的:

在JS Bin中查看

let source = new Array('second', 'third'); let items = new Array('first', ...source); items; // => ['first', 'second', 'third']

new Array('First', ...source)建立数组时使用了'First'元素以及source数组中的全部元素。

不管哪一种方式,你都应该倾向于使用数组字面量,由于它更简单直接。

2.3 有用的静态方法

当读到关于经过在构造器调用中传入一个数字来建立稀疏数组的部分时你可能好奇这有什么实际的用处。

ECMAScript 6增长了一些有用的方法如Array.prototype.fill()Array.from()。这两个方法均可以用来填充一个稀疏数组中的空slot。

让我使用fill()方法来建立一个包含5个0的数组:

在JS Bin中查看

let zeros = new Array(5).fill(0); zeros; // => [0, 0, 0, 0, 0]

new Array(5)建立了一个有5个空slot的稀疏数组。接着fill(0)方法用0填充了空slot。

静态方法Array.from()则有着更宽的使用场景。像上边的例子同样,让咱们建立一个包含5个0的数组:

在JS Bin中查看

let zeros = Array.from(new Array(5), () => 0); zeros; // => [0, 0, 0, 0, 0]

一个经过new Array(5)建立的长度为5的稀疏组数做为参数被传递给Array.from()。第二个参数做为一个返回0的映射函数。

共执行了5次迭代,每次迭代中箭头函数的返回值被用做数组的元素。

因为在每次迭代中都会执行映射函数,所以动态建立数组元素是可行的。让咱们建立一个包含15的数组:

在JS Bin中查看

let items = Array.from(new Array(5), (item, index) => index + 1); items; // => [1, 2, 3, 4, 5]

映射函数被调用时会传入两个参数:当前的item以及当前迭代的index。索引参数被用来生成元素:index + 1

Array.from()的第一个参数能够接受任何可迭代对象,这使得它更有价值。

让咱们使用一个生成器对象建立一个递增的数字列表:

在JS Bin中查看

function* generate(max) { let count = 0; while (max > count++) { yield count; } } let items = Array.from(generate(5)); items; // => [1, 2, 3, 4, 5] let itemsSpread = [...generate(5)]; itemsSpread; // => [1, 2, 3, 4, 5]

generate(max)是一个生成器函数,它会生成从一串从1max的数字。

Array.from(generate(5))使用一个生成器对象做为参数建立了一个包含15数字的数组。

使用spread运算符[...generate(5)]和数组字面量能够达到一样的目的。

3. 总结

数组初始化是操做集合时的常见操做。JavaScript提供了多种方法以及灵活性来实现该目的。

数组构造器的行为在不少状况下会让你感到意外。所以数组字面量是初始化数组实例更好,更简单的方式。

当数组须要根据基于每一个迭代元素的计算进行初始化时,Array.from()是一个不错的选择。

若是数组元素须要被填充为同一个值,使用Array.prototype.fill()new Array(length)的组合。

不要低估可迭代对象和生成器函数的能力,它们能够和spread运算符组合起来使用在数组字面量或是Array.from()中。

相关文章
相关标签/搜索