定义

数组的标准定义是:

一个存储元素的线性集合(collection),

元素可以通过索引来任意存取,

索引通常是数字,用来计算元素之间存储位置的偏移量。

几乎所有的编程语言都有类似的数据结构。

然而 JavaScript 的数组却略有不同。

JavaScript 中的数组是一种特殊的对象,

用来表示偏移量的索引(index)是该对象的属性,

索引可能是整数。

然而,这些数字索引在内部被转换为字符串类型,

这是因为 JavaScript 对象中 的属性名必须是字符串。

数组在 JavaScript 中只是一种特殊的对象,所以效率上不如其他 语言中的数组高。

常用操作

创建数组

大多数 JavaScript 专家推荐使用 [] 操作符

  1. var fruits = ['Apple', 'Banana'];
  2. console.log(fruits.length);
  3. // 2

通过索引访问数组元素

这里使用数组的 length 属性来控制循环次数,而不是直接使用数字。

JavaScript 中 的数组也是对象,数组的长度可以任意增长,超出其创建时指定的长度。

length 属性反映 的是当前数组中元素的个数,使用它,可以确保循环遍历了数组中的所有元素

  1. var first = fruits[0];
  2. // Apple
  3. var last = fruits[fruits.length - 1];
  4. // Banana

遍历数组

  1. fruits.forEach(function (item, index, array) {
  2. console.log(item, index);
  3. });
  4. // Apple 0
  5. // Banana 1

添加元素到数组的末尾

  1. var newLength = fruits.push('Orange');
  2. // newLength:3; fruits: ["Apple", "Banana", "Orange"]

删除数组末尾的元素

  1. var last = fruits.pop(); // remove Orange (from the end)
  2. // last: "Orange"; fruits: ["Apple", "Banana"];

删除数组最前面(头部)的元素

  1. var first = fruits.shift(); // remove Apple from the front
  2. // first: "Apple"; fruits: ["Banana"];

添加元素到数组的头部

  1. var newLength = fruits.unshift('Strawberry') // add to the front
  2. // ["Strawberry", "Banana"];

找出某个元素在数组中的索引

indexOf() 函数总是返回第一个与参数相同的元素的索 引。

lastIndexOf(),该函数返回相同元素中最后一个元 素的索引

  1. fruits.push('Mango');
  2. // ["Strawberry", "Banana", "Banana", "Mango"]
  3. var pos = fruits.indexOf('Banana');
  4. // 1
  5. var pos = fruits.lastIndexOf('Banana');
  6. // 2

通过索引删除某个元素

  1. var removedItem = fruits.splice(pos, 1); // this is how to remove an item
  2. // ["Strawberry", "Mango"]

从一个索引位置删除多个元素

  1. var vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot'];
  2. console.log(vegetables);
  3. // ["Cabbage", "Turnip", "Radish", "Carrot"]
  4. var pos = 1, n = 2;
  5. var removedItems = vegetables.splice(pos, n);
  6. // this is how to remove items, n defines the number of items to be removed,
  7. // from that position(pos) onward to the end of array.
  8. console.log(vegetables);
  9. // ["Cabbage", "Carrot"] (the original array is changed)
  10. console.log(removedItems);
  11. // ["Turnip", "Radish"]

复制一个数组

当把一个数组赋给另外一个数组时,只是为被赋值的数组增加了一个新的引用。

当你通过原引用修改了数组的值,另外一个引用也会感知到这个变化。

  1. var shallowCopy = fruits.slice(); // this is how to make a copy
  2. // ["Strawberry", "Mango"]

修改器方法

下面的这些方法会改变调用它们的对象自身的值:

Array.prototype.copyWithin()

在数组内部,将一段元素序列拷贝到另一段元素序列上,覆盖原有的值。

Array.prototype.fill()

将数组中指定区间的所有元素的值,都替换成某个固定的值。

Array.prototype.pop()

删除数组的最后一个元素,并返回这个元素。

Array.prototype.push()

在数组的末尾增加一个或多个元素,并返回数组的新长度。

Array.prototype.reverse()

颠倒数组中元素的排列顺序,即原先的第一个变为最后一个,原先的最后一个变为第一个。

Array.prototype.shift()

删除数组的第一个元素,并返回这个元素。

Array.prototype.sort()

对数组元素进行排序,并返回当前数组。

Array.prototype.splice()

在任意的位置给数组添加或删除任意个元素。

Array.prototype.unshift()

在数组的开头增加一个或多个元素,并返回数组的新长度。

访问方法

下面的这些方法绝对不会改变调用它们的对象的值,只会返回一个新的数组或者返回一个其它的期望值。

Array.prototype.concat()

返回一个由当前数组和其它若干个数组或者若干个非数组值组合而成的新数组。

Array.prototype.includes()

判断当前数组是否包含某指定的值,如果是返回 true,否则返回 false。

Array.prototype.join()

连接所有数组元素组成一个字符串。

Array.prototype.slice()

抽取当前数组中的一段元素组合成一个新数组。

Array.prototype.toSource() — 非标准

返回一个表示当前数组字面量的字符串。遮蔽了原型链上的 Object.prototype.toSource() 方法。

Array.prototype.toString()

返回一个由所有数组元素组合而成的字符串。遮蔽了原型链上的 Object.prototype.toString() 方法。

Array.prototype.toLocaleString()

返回一个由所有数组元素组合而成的本地化后的字符串。遮蔽了原型链上的 Object.prototype.toLocaleString() 方法。

Array.prototype.indexOf()

返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。

Array.prototype.lastIndexOf()

返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。

迭代方法

在下面的众多遍历方法中,有很多方法都需要指定一个回调函数作为参数。在每一个数组元素都分别执行完回调函数之前,数组的length属性会被缓存在某个地方,所以,如果你在回调函数中为当前数组添加了新的元素,那么那些新添加的元素是不会被遍历到的。此外,如果在回调函数中对当前数组进行了其它修改,比如改变某个元素的值或者删掉某个元素,那么随后的遍历操作可能会受到未预期的影响。总之,不要尝试在遍历过程中对原数组进行任何修改,虽然规范对这样的操作进行了详细的定义,但为了可读性和可维护性,请不要这样做。

Array.prototype.forEach()

为数组中的每个元素执行一次回调函数。

Array.prototype.entries()

返回一个数组迭代器对象,该迭代器会包含所有数组元素的键值对。

Array.prototype.every()

如果数组中的每个元素都满足测试函数,则返回 true,否则返回 false。

Array.prototype.some()

如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false。

Array.prototype.filter()

将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回。

Array.prototype.find()

找到第一个满足测试函数的元素并返回那个元素的值,如果找不到,则返回 undefined。

Array.prototype.findIndex()

找到第一个满足测试函数的元素并返回那个元素的索引,如果找不到,则返回 -1。

Array.prototype.keys()

返回一个数组迭代器对象,该迭代器会包含所有数组元素的键。

Array.prototype.map()

返回一个由回调函数的返回值组成的新数组。

Array.prototype.reduce()

从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。

Array.prototype.reduceRight()

从右到左为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。

Array.prototype.values()

返回一个数组迭代器对象,该迭代器会包含所有数组元素的值。

Array.prototype@@iterator)

和上面的 values() 方法是同一个函数。

Array.prototype.concat() concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
Array.prototype.copyWithin() copyWithin() 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。
Array.prototype.entries() entries() 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。
Array.prototype.every() every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
Array.prototype.fill() fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
Array.prototype.filter() filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
Array.prototype.find() find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
Array.prototype.findIndex() findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。
Array.prototype.flat() flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
Array.prototype.flatMap() flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 连着深度值为1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。
Array.prototype.forEach() forEach() 方法对数组的每个元素执行一次提供的函数。
Array.prototype.map() map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
Array.prototype.includes() includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。
Array.prototype.indexOf() indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
Array.prototype.lastIndexOf() lastIndexOf() 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。
Array.prototype.join() join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。
Array.prototype.keys() keys() 方法返回一个包含数组中每个索引键的Array Iterator对象。
Array.prototype.pop() pop()方法从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。
Array.prototype.push() push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
Array.prototype.reduce() reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
Array.prototype.reduceRight() reduceRight() 方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。
Array.prototype.reverse() reverse() 方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
Array.prototype.shift() shift() 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
Array.prototype.slice() slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。
Array.prototype.some() some() 方法测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。 如果用一个空数组进行测试,在任何情况下它返回的都是false。
Array.prototype.sort() sort() 方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的
Array.prototype.splice() splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
Array.prototype.toLocaleString() toLocaleString() 返回一个字符串表示数组中的元素。数组中的元素将使用各自的 toLocaleString 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 “,”)隔开。
Array.prototype.toString() toString() 返回一个字符串,表示指定的数组及其元素。
Array.prototype.unshift() unshift() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)
Array.prototype.values() values() 方法返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值

Array.length

JavaScript 数组的 length 属性和其数字下标之间有着紧密的联系。数组内置的几个方法(例如 joinsliceindexOf 等)都会考虑 length 的值。另外还有一些方法(例如 pushsplice 等)还会改变 length 的值。

也可以显式地给 length 赋一个更大的值:

  1. fruits.length = 10;
  2. console.log(Object.keys(fruits)); // ['0', '1', '2', '5']
  3. console.log(fruits.length); // 10

而为 length 赋一个更小的值则会删掉一部分元素:

  1. fruits.length = 2;
  2. console.log(Object.keys(fruits)); // ['0', '1']
  3. console.log(fruits.length); // 2

你可以设置 length 属性的值来截断任何数组。当通过改变length属性值来扩展数组时,实际元素的数目将会增加。例如:将一个拥有 2 个元素的数组的 length 属性值设为 3 时,那么这个数组将会包含3个元素,并且,第三个元素的值将会是 undefined 。

Array.from()

从类数组对象或者可迭代对象中创建一个新的数组实例。

Array.from() 方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。

  1. console.log(Array.from('foo'));
  2. // expected output: Array ["f", "o", "o"]
  3. console.log(Array.from([1, 2, 3], x => x + x));
  4. // expected output: Array [2, 4, 6]