--- title: Array slug: Web/JavaScript/Reference/Global_Objects/Array tags: - 数组 - 类 - 示例 - 全局对象 - JavaScript - 参考手册 browser-compat: javascript.builtins.Array translation_of: Web/JavaScript/Reference/Global_Objects/Array --- {{JSRef}} JavaScript的 **`Array`** 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。 ## 描述 数组是一种类列表对象,它的原型中提供了遍历和修改元素的相关操作。JavaScript 数组的长度和元素类型都是非固定的。因为数组的长度可随时改变,并且其数据在内存中也可以不连续,所以 JavaScript 数组不一定是密集型的,这取决于它的使用方式。一般来说,数组的这些特性会给使用带来方便,但如果这些特性不适用于你的特定使用场景的话,可以考虑使用类型数组 {{jsxref("TypedArray")}}。 只能用整数作为数组元素的索引,而不能用字符串。后者称为 [关联数组](https://en.wikipedia.org/wiki/Associative_array)。使用非整数并通过 [方括号](/zh-CN/docs/Web/JavaScript/Guide/Working_with_Objects#对象和属性) 或 [点号](/zh-CN/docs/Web/JavaScript/Reference/Operators/Property_Accessors) 来访问或设置数组元素时,所操作的并不是数组列表中的元素,而是数组对象的 [属性集合](/zh-CN/docs/Web/JavaScript/Data_structures#属性) 上的变量。数组对象的属性和数组元素列表是分开存储的,并且数组的遍历和修改操作也不能作用于这些命名属性。 ### 常见操作 **创建数组** ```js let fruits = ['Apple', 'Banana'] console.log(fruits.length) // 2 ``` **通过索引访问数组元素** ```js let first = fruits[0] // Apple let last = fruits[fruits.length - 1] // Banana ``` **遍历数组** ```js fruits.forEach(function(item, index, array) { console.log(item, index) }) // Apple 0 // Banana 1 ``` **添加元素到数组的末尾** ```js let newLength = fruits.push('Orange') // ["Apple", "Banana", "Orange"] ``` **删除数组末尾的元素** ```js let last = fruits.pop() // remove Orange (from the end) // ["Apple", "Banana"] ``` **删除数组头部元素** ```js let first = fruits.shift() // remove Apple from the front // ["Banana"] ``` **添加元素到数组的头部** ```js let newLength = fruits.unshift('Strawberry') // add to the front // ["Strawberry", "Banana"] ``` **找出某个元素在数组中的索引** ```js fruits.push('Mango') // ["Strawberry", "Banana", "Mango"] let pos = fruits.indexOf('Banana') // 1 ``` **通过索引删除某个元素** ```js let removedItem = fruits.splice(pos, 1) // this is how to remove an item // ["Strawberry", "Mango"] ``` **从一个索引位置删除多个元素** ```js let vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot'] console.log(vegetables) // ["Cabbage", "Turnip", "Radish", "Carrot"] let pos = 1 let n = 2 let removedItems = vegetables.splice(pos, n) // this is how to remove items, n defines the number of items to be removed, // starting at the index position specified by pos and progressing toward the end of array. console.log(vegetables) // ["Cabbage", "Carrot"] (the original array is changed) console.log(removedItems) // ["Turnip", "Radish"] ``` **复制一个数组** ```js let shallowCopy = fruits.slice() // this is how to make a copy // ["Strawberry", "Mango"] ``` ### 访问数组元素 JavaScript 数组的索引是从0开始的,第一个元素的索引为0,最后一个元素的索引等于该数组的 {{jsxref("Array.length", "长度")}} 减1。 如果指定的索引是一个无效值,JavaScript 数组并不会报错,而是会返回 `undefined`。 ```js let arr = ['this is the first element', 'this is the second element', 'this is the last element'] console.log(arr[0]) // logs 'this is the first element' console.log(arr[1]) // logs 'this is the second element' console.log(arr[arr.length - 1]) // logs 'this is the last element' ``` 虽然数组元素可以看做是数组对象的属性,就像 `toString` 一样,但是下面的写法是错误的,运行时会抛出 `SyntaxError` 异常,而原因则是使用了非法的属性名: ```js console.log(arr.0) // a syntax error ``` 并不是 JavaScript 数组有什么特殊之处,而是因为在 JavaScript 中,以数字开头的属性不能用点号引用,必须用方括号。 比如,如果一个对象有一个名为 `3d` 的属性,那么只能用方括号来引用它。下面是具体的例子: ```js let years = [1950, 1960, 1970, 1980, 1990, 2000, 2010] console.log(years.0) // a syntax error console.log(years[0]) // works properly ``` ```js renderer.3d.setTexture(model, 'character.png') // a syntax error renderer['3d'].setTexture(model, 'character.png') // works properly ``` 注意在 `3d` 那个例子中,引号是必须的。你也可以将数组的索引用引号引起来,比如 `years[2]` 可以写成 `years['2']`。 `years[2]` 中的 2 会被 JavaScript 解释器通过调用 `toString` 隐式转换成字符串。正因为这样,`'2'` 和 `'02'` 在 `years` 中所引用的可能是不同位置上的元素。而下面这个例子也可能会打印 `true`: ```js console.log(years['2'] != years['02']) ``` ### 数组长度与数字下标之间的关系 JavaScript 数组的 {{jsxref("Array.length", "length")}} 属性和其数字下标之间有着紧密的联系。 数组内置的几个方法(例如 {{jsxref("Array.join", "join")}}、{{jsxref("Array.slice", "slice")}}、{{jsxref("Array.indexOf", "indexOf")}} 等)都会考虑 {{jsxref("Array.length", "length")}} 的值。 另外还有一些方法(例如 {{jsxref("Array.push", "push")}}、{{jsxref("Array.splice", "splice")}} 等)还会改变 {{jsxref("Array.length", "length")}} 的值。 ```js const fruits = [] fruits.push('banana', 'apple', 'peach') console.log(fruits.length) // 3 ``` 使用一个合法的下标为数组元素赋值,并且该下标超出了当前数组的大小的时候,解释器会同时修改 {{jsxref("Array.length", "length")}} 的值: ```js fruits[5] = 'mango' console.log(fruits[5]) // 'mango' console.log(Object.keys(fruits)) // ['0', '1', '2', '5'] console.log(fruits.length) // 6 ``` 也可以显式地给 {{jsxref("Array.length", "length")}} 赋一个更大的值: ```js fruits.length = 10 console.log(fruits) // ['banana', 'apple', 'peach', empty x 2, 'mango', empty x 4] console.log(Object.keys(fruits)) // ['0', '1', '2', '5'] console.log(fruits.length) // 10 console.log(fruits[8]) // undefined ``` 而为 {{jsxref("Array.length", "length")}} 赋一个更小的值则会删掉一部分元素: ```js fruits.length = 2 console.log(Object.keys(fruits)) // ['0', '1'] console.log(fruits.length) // 2 ``` 这一节的内容在 {{jsxref("Array.length")}} 中有更详细的介绍。 ### 正则匹配结果所返回的数组 使用正则表达式匹配字符串可以得到一个数组。这个数组中包含本次匹配的相关信息和匹配结果。{{jsxref("RegExp.exec")}}、{{jsxref("String.match")}}、{{jsxref("String.replace")}} 都会返回这样的数组。 看下面的例子和例子下面的表格: ```js // Match one d followed by one or more b's followed by one d // Remember matched b's and the following d // Ignore case const myRe = /d(b+)(d)/i const myArray = myRe.exec('cdbBdbsbz') ``` 该正则匹配返回的数组包含以下属性和元素:
属性/元素 | 说明 | 示例 |
---|---|---|
input {{ReadOnlyInline}} |
正则表达式所匹配的原始字符串 | "cdbBdbsbz" |
index {{ReadOnlyInline}} |
匹配到的子串在原始字符串中的索引 | 1 |
[0] {{ReadOnlyInline}} |
最后匹配到的子串 | "dbBd" |
[1], ...[n] {{ReadOnlyInline}} |
正则表达式中所指定的分组所匹配到的子串,其数量由正则中的分组数量决定,无最大上限 |
[1]: "bB"
|