Array
JavaScript的 <code>Array</code> 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。
创建数组
通过索引访问数组元素
遍历数组
添加元素到数组的末尾
删除数组末尾的元素
删除数组最前面(头部)的元素
添加元素到数组的头部
找出某个元素在数组中的索引
通过索引删除某个元素
从一个索引位置删除多个元素
复制一个数组
<dl></dl>
<dt></dt>
<dt><code>elementN</code></dt>
<dd></dd>
<code>Array</code> 构造器会根据给定的元素创建一个 JavaScript 数组,但是当仅有一个参数且为数字时除外(详见下面的 <code>arrayLength</code> 参数)。注意,后面这种情况仅适用于用 <code>Array</code> 构造器创建数组,而不适用于用方括号创建的数组字面量。
<dt><code>arrayLength</code></dt>
<dd>一个范围在 0 到 232-1 之间的整数,此时将返回一个 <code>length</code> 的值等于 <code>arrayLength</code> 的数组对象(言外之意就是该数组此时并没有包含任何实际的元素,不能理所当然地认为它包含 <code>arrayLength</code> 个值为 <code>undefined</code> 的元素)。如果传入的参数不是有效值,则会抛出 <code>RangeError</code> 异常。</dd>
数组是一种类列表对象,它的原型中提供了遍历和修改元素的相关操作。JavaScript 数组的长度和元素类型都是非固定的。因为数组的长度可随时改变,并且其数据在内存中也可以不连续,所以 JavaScript 数组不一定是密集型的,这取决于它的使用方式。一般来说,数组的这些特性会给使用带来方便,但如果这些特性不适用于你的特定使用场景的话,可以考虑使用类型数组 <code>TypedArray</code>。
只能用整数作为数组元素的索引,而不能用字符串。后者称为关联数组。使用非整数并通过方括号或点号来访问或设置数组元素时,所操作的并不是数组列表中的元素,而是数组对象的属性集合上的变量。数组对象的属性和数组元素列表是分开存储的,并且数组的遍历和修改操作也不能作用于这些命名属性。
JavaScript 数组的索引是从0开始的,第一个元素的索引为0,最后一个元素的索引等于该数组的长度减1。如果指定的索引是一个无效值,JavaScript 数组并不会报错,而是会返回 <code>undefined</code>。
虽然数组元素可以看做是数组对象的属性,就像 <code>toString</code> 一样,但是下面的写法是错误的,运行时会抛出 <code>SyntaxError</code> 异常,而原因则是使用了非法的属性名:
并不是 JavaScript 数组有什么特殊之处,而是因为在 JavaScript 中,以数字开头的属性不能用点号引用,必须用方括号。比如,如果一个对象有一个名为 <code>3d</code> 的属性,那么只能用方括号来引用它。下面是具体的例子:
注意在 <code>3d</code> 那个例子中,引号是必须的。你也可以将数组的索引用引号引起来,比如 <code>years[2]</code> 可以写成 <code>years['2']</code>。 <code>years[2]</code> 中的 2 会被 JavaScript 解释器通过调用 <code>toString</code> 隐式转换成字符串。正因为这样,<code>'2'</code> 和 <code>'02'</code> 在 <code>years</code> 中所引用的可能是不同位置上的元素。而下面这个例子也可能会打印 <code>true</code>:
类似地,如果对象的属性名称是保留字(最好不要这么做!),那么就只能通过字符串的形式用方括号来访问(从 firefox 40.0a2 开始也支持用点号访问了):
JavaScript 数组的 <code>length</code> 属性和其数字下标之间有着紧密的联系。数组内置的几个方法(例如 <code>join</code>、<code>slice</code>、<code>indexOf</code> 等)都会考虑 <code>length</code> 的值。另外还有一些方法(例如 <code>push</code>、<code>splice</code> 等)还会改变 <code>length</code> 的值。
使用一个合法的下标为数组元素赋值,并且该下标超出了当前数组的大小的时候,解释器会同时修改 <code>length</code> 的值:
也可以显式地给 <code>length</code> 赋一个更大的值:
而为 <code>length</code> 赋一个更小的值则会删掉一部分元素:
这一节的内容在 <code>Array.length</code> 中有更详细的介绍。
使用正则表达式匹配字符串可以得到一个数组。这个数组中包含本次匹配的相关信息和匹配结果。<code>RegExp.exec</code>、<code>String.match</code>、<code>String.replace</code> 都会返回这样的数组。看下面的例子和例子下面的表格:
该正则匹配返回的数组包含以下属性和元素:
属性/元素
说明
示例
<code>input</code>
只读属性,原始字符串
cdbBdbsbz
<code>index</code>
只读属性,匹配到的子串在原始字符串中的索引
1
<code>[0]</code>
只读元素,本次匹配到的子串
dbBd
<code>[1], ...[n]</code>
只读元素,正则表达式中所指定的分组所匹配到的子串,其数量由正则中的分组数量决定,无最大上限
[1]: bB
[2]: d
<code>Array.length</code>
<code>Array</code> 构造函数的 length 属性,其值为1(注意该属性为静态属性,不是数组实例的 length 属性)。
<dt><code>get Array[@@species]</code></dt>
<dd>返回 <code>Array</code> 构造函数。</dd>
<dt><code>Array.prototype</code></dt>
<dd>通过数组的原型对象可以为所有数组对象添加属性。</dd>
<dt><code>Array.from()</code></dt>
<dd>从类数组对象或者可迭代对象中创建一个新的数组实例。</dd>
<dt><code>Array.isArray()</code></dt>
<dd>用来判断某个变量是否是一个数组对象。</dd>
<dt><code>Array.of()</code></dt>
<dd>根据一组参数来创建新的数组实例,支持任意的参数数量和类型。</dd>
所有数组实例都会从 <code>Array.prototype</code> 继承属性和方法。修改 <code>Array</code> 的原型会影响到所有的数组实例。
<dt><code>Array.prototype.constructor</code></dt>
<dd>所有的数组实例都继承了这个属性,它的值就是 <code>Array</code>,表明了所有的数组都是由 <code>Array</code> 构造出来的。</dd>
<dt><code>Array.prototype.length</code></dt>
<dd>上面说了,因为 <code>Array.prototype</code> 也是个数组,所以它也有 <code>length</code> 属性,这个值为 <code>0</code>,因为它是个空数组。</dd>
下面的这些方法会改变调用它们的对象自身的值:
<code>Array.prototype.copyWithin()</code>
<dd>在数组内部,将一段元素序列拷贝到另一段元素序列上,覆盖原有的值。</dd>
<code>Array.prototype.fill()</code>
<dd>将数组中指定区间的所有元素的值,都替换成某个固定的值。</dd>
<dt><code>Array.prototype.pop()</code></dt>
<dd>删除数组的最后一个元素,并返回这个元素。</dd>
<dt><code>Array.prototype.push()</code></dt>
<dd>在数组的末尾增加一个或多个元素,并返回数组的新长度。</dd>
<dt><code>Array.prototype.reverse()</code></dt>
<dd>颠倒数组中元素的排列顺序,即原先的第一个变为最后一个,原先的最后一个变为第一个。</dd>
<dt><code>Array.prototype.shift()</code></dt>
<dd>删除数组的第一个元素,并返回这个元素。</dd>
<dt><code>Array.prototype.sort()</code></dt>
<dd>对数组元素进行排序,并返回当前数组。</dd>
<dt><code>Array.prototype.splice()</code></dt>
<dd>在任意的位置给数组添加或删除任意个元素。</dd>
<dt><code>Array.prototype.unshift()</code></dt>
<dd>在数组的开头增加一个或多个元素,并返回数组的新长度。 </dd>
下面的这些方法绝对不会改变调用它们的对象的值,只会返回一个新的数组或者返回一个其它的期望值。
<dt><code>Array.prototype.concat()</code></dt>
<dd>返回一个由当前数组和其它若干个数组或者若干个非数组值组合而成的新数组。</dd>
<code>Array.prototype.includes()</code>
<dd>判断当前数组是否包含某指定的值,如果是返回 <code>true</code>,否则返回 <code>false</code>。</dd>
<dt><code>Array.prototype.join()</code></dt>
<dd>连接所有数组元素组成一个字符串。</dd>
<dt><code>Array.prototype.slice()</code></dt>
<dd>抽取当前数组中的一段元素组合成一个新数组。</dd>
<code>Array.prototype.toSource()</code>
<dd>返回一个表示当前数组字面量的字符串。遮蔽了原型链上的 <code>Object.prototype.toSource()</code> 方法。</dd>
<dt><code>Array.prototype.toString()</code></dt>
<dd>返回一个由所有数组元素组合而成的字符串。遮蔽了原型链上的 <code>Object.prototype.toString()</code> 方法。</dd>
<dt><code>Array.prototype.toLocaleString()</code></dt>
<dd>返回一个由所有数组元素组合而成的本地化后的字符串。遮蔽了原型链上的 <code>Object.prototype.toLocaleString()</code> 方法。</dd>
<dt><code>Array.prototype.indexOf()</code></dt>
<dd>返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。</dd>
<dt><code>Array.prototype.lastIndexOf()</code></dt>
<dd>返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。 </dd>
在下面的众多遍历方法中,有很多方法都需要指定一个回调函数作为参数。在每一个数组元素都分别执行完回调函数之前,数组的length属性会被缓存在某个地方,所以,如果你在回调函数中为当前数组添加了新的元素,那么那些新添加的元素是不会被遍历到的。此外,如果在回调函数中对当前数组进行了其它修改,比如改变某个元素的值或者删掉某个元素,那么随后的遍历操作可能会受到未预期的影响。总之,不要尝试在遍历过程中对原数组进行任何修改,虽然规范对这样的操作进行了详细的定义,但为了可读性和可维护性,请不要这样做。
<dt><code>Array.prototype.forEach()</code></dt>
<dd>为数组中的每个元素执行一次回调函数。</dd>
<code>Array.prototype.entries()</code>
<dd>返回一个数组迭代器对象,该迭代器会包含所有数组元素的键值对。</dd>
<dt><code>Array.prototype.every()</code></dt>
<dt><code>Array.prototype.some()</code></dt>
<dd>如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false。</dd>
<dt><code>Array.prototype.filter()</code></dt>
<dd>将所有在过滤函数中返回 <code>true</code> 的数组元素放进一个新数组中并返回。</dd>
<code>Array.prototype.find()</code>
<dd>找到第一个满足测试函数的元素并返回那个元素的值,如果找不到,则返回 <code>undefined</code>。</dd>
<code>Array.prototype.findIndex()</code>
<dd>找到第一个满足测试函数的元素并返回那个元素的索引,如果找不到,则返回 <code>-1</code>。</dd>
<code>Array.prototype.keys()</code>
<dd>返回一个数组迭代器对象,该迭代器会包含所有数组元素的键。</dd>
<dt><code>Array.prototype.map()</code></dt>
<dd>返回一个由回调函数的返回值组成的新数组。</dd>
<dt><code>Array.prototype.reduce()</code></dt>
<dd>从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。</dd>
<dt><code>Array.prototype.reduceRight()</code></dt>
<dd>从右到左为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。</dd>
<code>Array.prototype.values()</code>
<dd>返回一个数组迭代器对象,该迭代器会包含所有数组元素的值。</dd>
<code>Array.prototype[@@iterator]()</code>
<dd>和上面的 <code>values() 方法是同一个函数。</code> </dd>
泛型方法是非标准,并且已弃用,有可能不久就会移除。 需注意的是此方法同时有跨浏览器问题. 但是 Github上有可用的shim。
有时我们会希望在字符串或其他类数组对象上使用数组所提供的方法(如函数的 arguments)。此时你可以把一个字符串作为一个字符数组来看待(也就是说,把非数组以某种方式看成是一个数组)。比如,可以用下面的方法来检查变量 <code>str</code> 中的字符是否都是字母:
这种方法能够行得通,但不够简洁,JavaScript 1.6 中引入了一个泛型化的简写形式:
<code>String</code> 对象也包含一些泛型方法,见: Generics。
注意,这些并不属于 ECMAScript 标准,也不能在非 Gecko 浏览器中使用。你可以用标准方法 <code>Array.from()</code> 来替代上面的写法, <code>from</code> 方法可以将一个对象转换为真正的数组(虽然老的浏览器可能不支持):