recursal/MDN huggingface dataset:
Array.prototype[@@iterator]()
=============================

`Array` 实例的 **`[@@iterator]()`** 方法实现了迭代协议，允许数组被大多数期望可迭代对象的语法所使用，例如展开语法和 `for...of` 循环。它返回一个数组迭代器对象，该对象会产生数组中每个索引的值。

该属性的初始值与 `Array.prototype.values` 属性的初始值是相同的函数对象。

尝试一下
----

语法
--


```js
array[Symbol.iterator]()
```

### 返回值

与 `Array.prototype.values()` 相同的返回值：一个新的可迭代迭代器对象，它会生成数组中每个索引的值。

示例
--

### 使用 for...of 循环进行迭代

请注意，你很少需要直接调用此方法。`@@iterator` 方法的存在使数组可迭代，并且像 `for...of` 循环这样的迭代语法会自动调用此方法以获得要遍历的迭代器。

#### HTML


```html
<ul id="letterResult"></ul>
```


#### JavaScript


```js
const arr = ["a", "b", "c"];
const letterResult = document.getElementById("letterResult");
for (const letter of arr) {
  const li = document.createElement("li");
  li.textContent = letter;
  letterResult.appendChild(li);
}
```


#### 结果

### 手动执行迭代器

你仍然可以手动调用返回迭代器对象的 `next()` 方法，以实现对迭代过程的最大控制。


```js
const arr = ["a", "b", "c", "d", "e"];
const arrIter = arr[Symbol.iterator]();
console.log(arrIter.next().value); // a
console.log(arrIter.next().value); // b
console.log(arrIter.next().value); // c
console.log(arrIter.next().value); // d
console.log(arrIter.next().value); // e
```

### 使用相同的函数处理字符串和字符串数组

因为字符串和数组都实现了可迭代协议，所以可以设计一个通用函数以相同的方式处理这两种输入。这比直接调用 `Array.prototype.values()` 更好，后者要求输入是一个数组，或者至少是一个具有这种方法的对象。


```js
function logIterable(it) {
  if (typeof it[Symbol.iterator] !== "function") {
    console.log(it, "不可迭代。");
    return;
  }
  for (const letter of it) {
    console.log(letter);
  }
}

// 数组
logIterable(["a", "b", "c"]);
// a
// b
// c

// 字符串
logIterable("abc");
// a
// b
// c

// 数值
logIterable(123);
// 123 不可迭代。
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-array.prototype-@@iterator |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Array.prototype[@@iterator]` 的 polyfill
* 索引集合类
* `Array`
* `Array.prototype.keys()`
* `Array.prototype.entries()`
* `Array.prototype.values()`
* `TypedArray.prototype[@@iterator]()`
* `String.prototype[@@iterator]()`
* `Symbol.iterator`
* 迭代协议
Array.prototype.lastIndexOf()
=============================

概述
--

**`lastIndexOf()`** 方法返回数组中给定元素最后一次出现的索引，如果不存在则返回 -1。该方法从 `fromIndex` 开始向前搜索数组。

尝试一下
----

语法
--


```js
lastIndexOf(searchElement)
lastIndexOf(searchElement, fromIndex)
```

### 参数

`searchElement`

被查找的元素。

`fromIndex` 可选

以 0 起始的索引，表明反向搜索的起始位置，会被转换为整数。

* 如果 `fromIndex < 0`，则从数组末尾开始倒数计数——即使用 `fromIndex + array.length` 的值。
* 如果 `fromIndex < -array.length`，则不搜索数组并返回 `-1`。从概念上讲，你可以把它想象成从数组开始之前不存在的位置开始反向搜索，这条路径上没有任何数组元素，因此 `searchElement` 永远不会被找到。
* 如果 `fromIndex >= array.length` 或者省略了 `fromIndex`，则使用 `array.length - 1`，这会导致搜索整个数组。可以将其理解为从数组尾部之后不存在的位置开始向前搜索。最终会访问到数组最后一个元素，并继续向前开始实际搜索数组元素。

### 返回值

数组中该元素最后一次出现的索引，如未找到返回 **-1**。

描述
--

`lastIndexOf` 使用严格相等（与 `===` 运算符使用的算法相同）比较 `searchElement` 和数组中的元素。`NaN` 值永远不会被比较为相等，因此当 `searchElement` 为 `NaN` 时 `lastIndexOf()` 总是返回 `-1`。

`lastIndexOf()` 方法会跳过稀疏数组中的空槽。

`lastIndexOf()` 方法是通用的。它只期望 `this` 值具有 `length` 属性和整数键属性。

示例
--

### 使用 lastIndexOf()

下例使用 `lastIndexOf()` 定位数组中的值。


```js
const numbers = [2, 5, 9, 2];
numbers.lastIndexOf(2); // 3
numbers.lastIndexOf(7); // -1
numbers.lastIndexOf(2, 3); // 3
numbers.lastIndexOf(2, 2); // 0
numbers.lastIndexOf(2, -2); // 0
numbers.lastIndexOf(2, -1); // 3
```


你不能用 `lastIndexOf()` 来搜索 `NaN`。


```js
const array = [NaN];
array.lastIndexOf(NaN); // -1
```

### 查找元素出现的所有索引

下例使用 `lastIndexOf` 查找到一个元素在数组中所有的索引（下标），并在找到它们时用 `push` 将它们添加到另一个数组中。


```js
const indices = [];
const array = ["a", "b", "a", "c", "a", "d"];
const element = "a";
let idx = array.lastIndexOf(element);
while (idx !== -1) {
  indices.push(idx);
  idx = idx > 0 ? array.lastIndexOf(element, idx - 1) : -1;
}

console.log(indices);
// [4, 2, 0]
```


需要注意的是，这里必须单独处理 `idx === 0` 的情况，因为如果该元素是数组的第一个元素，则无论 `fromIndex` 参数的值为何，它总是会被找到。这与 `indexOf` 方法不同。

### 在稀疏数组上使用 lastIndexOf()

你不能使用 `lastIndexOf()` 来搜索稀疏数组中的空槽。


```js
console.log([1, , 3].lastIndexOf(undefined)); // -1
```

### 在非数组对象上调用 lastIndexOf()

`lastIndexOf()` 方法读取 `this` 的 `length` 属性，然后访问每个整数索引。


```js
const arrayLike = {
  length: 3,
  0: 2,
  1: 3,
  2: 2,
};
console.log(Array.prototype.lastIndexOf.call(arrayLike, 2));
// 2
console.log(Array.prototype.lastIndexOf.call(arrayLike, 5));
// -1
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-array.prototype.lastindexof |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Array.prototype.lastIndexOf` 的 polyfill
* 索引集合类
* `Array`
* `Array.prototype.findIndex()`
* `Array.prototype.findLastIndex()`
* `Array.prototype.indexOf()`
* `TypedArray.prototype.lastIndexOf()`
* `String.prototype.lastIndexOf()`
Array.prototype.unshift()
=========================

**`unshift()`** 方法将指定元素添加到数组的开头，并返回数组的新长度。

尝试一下
----

语法
--


```js
unshift()
unshift(element1)
unshift(element1, element2)
unshift(element1, element2, /\* …, \*/ elementN)
```

### 参数

`element1`、…、`elementN`

添加到 `arr` 开头的元素。

### 返回值

返回调用方法对象的新 `length` 属性。

描述
--

`unshift()` 方法将给定的值插入到类数组对象的开头。

`Array.prototype.push()` 有着和 `unshift()` 相似的行为，但是其将元素插入到数组的末尾。

请注意，如果多个元素作为参数传递，它们将被插入到对象开头的块中，与它们作为参数传递的顺序完全相同。因此，调用**一次** `unshift()` 方法并传递 `n` 个参数，与调用 `n` 次并传递 **1** 个参数（例如使用循环），不会产生相同的结果。

请看示例：


```js
let arr = [4, 5, 6];

arr.unshift(1, 2, 3);
console.log(arr);
// [1, 2, 3, 4, 5, 6]

arr = [4, 5, 6]; // 重置数组

arr.unshift(1);
arr.unshift(2);
arr.unshift(3);

console.log(arr);
// [3, 2, 1, 4, 5, 6]
```


`unshift()` 方法是通用的。它只期望 `this` 值具有 `length` 属性和整数键属性。虽然字符串也是类似于数组的，但这个方法不适用于它们，因为字符串是不可变的。

示例
--

### 使用 unshift()


```js
const arr = [1, 2];

arr.unshift(0); // 调用的结果是 3，这是新的数组长度。
// 数组是 [0, 1, 2]

arr.unshift(-2, -1); // 新的数组长度是 5
// 数组是 [-2, -1, 0, 1, 2]

arr.unshift([-4, -3]); // 新的数组长度是 6
// 数组是 [[-4, -3], -2, -1, 0, 1, 2]

arr.unshift([-7, -6], [-5]); // 新的数组长度是 8
// 数组是 [ [-7, -6], [-5], [-4, -3], -2, -1, 0, 1, 2 ]
```

### 在非数组对象中使用 unshift()

`unshift` 方法会读取 `this` 的 `length` 属性。然后，它将 `0` 到 `length - 1` 范围内的所有属性按参数数量右移，并将每个索引从 `0` 开始，并将参数传递给 `unshift()`。最后，它将 `length` 设置为之前的长度加上前置元素的数量。


```js
const arrayLike = {
  length: 3,
  unrelated: "foo",
  2: 4,
};
Array.prototype.unshift.call(arrayLike, 1, 2);
console.log(arrayLike);
// { '0': 1, '1': 2, '4': 4, length: 5, unrelated: 'foo' }

const plainObj = {};
// 这里没有长度属性，所以这里的长的为 0
Array.prototype.unshift.call(plainObj, 1, 2);
console.log(plainObj);
// { '0': 1, '1': 2, length: 2 }
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-array.prototype.unshift |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Array.prototype.unshift` 的 Polyfill，并对此方法进行了修复
* 索引集合类
* `Array`
* `Array.prototype.push()`
* `Array.prototype.pop()`
* `Array.prototype.shift()`
* `Array.prototype.concat()`
* `Array.prototype.splice()`
Array() 构造函数
============

**`Array()`** 构造函数用于创建 `Array` 对象。

语法
--


```js
new Array()
new Array(element0)
new Array(element0, element1)
new Array(element0, element1, /\* … ,\*/ elementN)
new Array(arrayLength)

Array()
Array(element0)
Array(element0, element1)
Array(element0, element1, /\* … ,\*/ elementN)
Array(arrayLength)
```


**备注：** 调用 `Array()` 时可以使用或不使用 `new`。两者都会创建一个新的 `Array` 实例。

### 参数

`elementN`

`Array` 构造函数会根据给定的元素创建一个 JavaScript 数组，但是当仅有一个参数且为数字时除外（详见下面的 `arrayLength` 参数）。注意，后者仅适用于用 Array 构造函数创建数组，而不适用于用方括号创建的数组字面量。

`arrayLength`

如果传递给 `Array` 构造函数的唯一参数是介于 0 到 232 - 1（含）之间的整数，这将返回一个新的 JavaScript 数组，其 `length` 属性设置为该数字（**注意**：这意味着一个由 `arrayLength` 个空槽组成的数组，而不是具有实际 `undefined` 值的槽——参见稀疏数组）。

### 异常

`RangeError`

如果只有一个参数（`arrayLength`）且其值不在 0 到 232 - 1（包括）之间，则会触发异常。

示例
--

### 数组字面量

可以通过使用数组字面量创建数组：


```js
const fruits = ["Apple", "Banana"];

console.log(fruits.length); // 2
console.log(fruits[0]); // "Apple"
```

### 单个参数的 Array 构造函数

可以通过单个数字参数的构造函数创建数组，数组的长度为传入的参数，该数组不包含任何实际的元素。


```js
const arrayEmpty = new Array(2);

console.log(arrayEmpty.length); // 2
console.log(arrayEmpty[0]); // undefined；实际上是一个空槽
console.log(0 in arrayEmpty); // false
console.log(1 in arrayEmpty); // false
```



```js
const arrayOfOne = new Array("2"); // 这里是字符串 "2" 而不是数字 2

console.log(arrayOfOne.length); // 1
console.log(arrayOfOne[0]); // "2"
```

### 多个参数的 Array 构造函数

如果向构造函数传入多个参数，则会创建一个包含给定元素的新 `Array`。


```js
const fruits = new Array("Apple", "Banana");

console.log(fruits.length); // 2
console.log(fruits[0]); // "Apple"
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-array-constructor |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 索引集合类
* `Array`
Array.prototype.flat()
======================

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.

* Learn more
* See full compatibility
* Report feedback
**`flat()`** 方法创建一个新的数组，并根据指定深度递归地将所有子数组元素拼接到新的数组中。

尝试一下
----

语法
--


```js
flat()
flat(depth)
```

### 参数

`depth` 可选

指定要提取嵌套数组的结构深度，默认值为 1。

### 返回值

一个新的数组，其中包含拼接后的子数组元素。

描述
--

`flat()` 方法属于复制方法。它不会改变 `this` 数组，而是返回一个浅拷贝，该浅拷贝包含了原始数组中相同的元素。

如果待展开的数组是稀疏的，`flat()` 方法会忽略其中的空槽。例如，如果 `depth` 是 1，那么根数组和第一层嵌套数组中的空槽都会被忽略，但在更深的嵌套数组中的空槽则会与这些数组一起保留。

`flat()` 方法是通用的。它只需要 `this` 值具有 `length` 属性和整数键属性即可。但是，如果要展开元素，则它们必须是数组。

示例
--

### 展平嵌套数组


```js
const arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

const arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

### 在稀疏数组上使用 flat()

`flat()` 方法删除数组中的空槽：


```js
const arr5 = [1, 2, , 4, 5];
console.log(arr5.flat()); // [1, 2, 4, 5]

const array = [1, , 3, ["a", , "c"]];
console.log(array.flat()); // [ 1, 3, "a", "c" ]

const array2 = [1, , 3, ["a", , ["d", , "e"]]];
console.log(array2.flat()); // [ 1, 3, "a", ["d", empty, "e"] ]
console.log(array2.flat(2)); // [ 1, 3, "a", "d", "e"]
```

### 在非数组对象上调用 flat()

`flat()` 方法读取 `this` 的 `length` 属性，然后访问每个整数索引。如果元素不是数组，则直接将其附加到结果中。如果元素是数组，则根据 `depth` 参数进行展开操作。


```js
const arrayLike = {
  length: 3,
  0: [1, 2],
  // 嵌套的类数组对象不会被展平
  1: { length: 2, 0: 3, 1: 4 },
  2: 5,
};
console.log(Array.prototype.flat.call(arrayLike));
// [ 1, 2, { '0': 3, '1': 4, length: 2 }, 5 ]
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-array.prototype.flat |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Array.prototype.flat` 的 polyfill
* 索引集合类
* `Array`
* `Array.prototype.concat()`
* `Array.prototype.flatMap()`
* `Array.prototype.map()`
* `Array.prototype.reduce()`
Array.prototype.toReversed()
============================

`Array` 实例的 **`toReversed()`** 方法是 `reverse()` 方法对应的复制版本。它返回一个元素顺序相反的新数组。

语法
--


```js
toReversed()
```

### 返回值

一个包含以相反顺序排列元素的新数组。

描述
--

`toReversed()` 方法将调用该方法的数组对象的元素以相反的顺序调换，并返回一个新数组。

当用于稀疏数组时，`toReversed()` 方法迭代空槽，就像它们的值是 `undefined` 一样。

`toReversed()` 方法是通用的。它只期望 `this` 值具有 `length` 属性和整数键属性。

示例
--

### 反转数组中的元素

下面的示例创建了一个包含三个元素的数组 `items`，然后创建了一个新的数组，该数组是 `items` 的反转。`items` 数组保持不变。


```js
const items = [1, 2, 3];
console.log(items); // [1, 2, 3]

const reversedItems = items.toReversed();
console.log(reversedItems); // [3, 2, 1]
console.log(items); // [1, 2, 3]
```

### 在稀疏数组上使用 toReversed()

`toReversed()` 的返回值永远不是稀疏的。空槽在返回的数组中变为 `undefined`。


```js
console.log([1, , 3].toReversed()); // [3, undefined, 1]
console.log([1, , 3, 4].toReversed()); // [4, 3, undefined, 1]
```

### 在非数组对象上调用 toReversed()

`toReversed()` 方法读取 `this` 的 `length` 属性。然后按降序访问 `length - 1` 和 `0` 之间的每个索引，并将原始数组中该索引的值添加到新数组相应的索引中。


```js
const arrayLike = {
  length: 3,
  unrelated: "foo",
  2: 4,
};
console.log(Array.prototype.toReversed.call(arrayLike));
// [4, undefined, undefined]
// '0' 和 '1' 两个索引不存在，所以它们会变成 undefined
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-array.prototype.toreversed |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Array.prototype.toReversed` 的 polyfill
* `Array.prototype.reverse()`
* `Array.prototype.toSorted()`
* `Array.prototype.toSpliced()`
* `Array.prototype.with()`
* `TypedArray.prototype.toReversed()` (en-US)
Array[@@species]
================

**`Array[@@species]`** 是一个静态访问器属性，用于返回构造函数，构造函数用于构造数组方法返回值。

**警告：** `@@species` 的存在允许执行任意代码，这可能会产生安全漏洞。它还会使某些优化变得更加困难。引擎开发者正在调查是否要移除此特性。如果可能，请避免依赖它。现代数组方法，如 `toReversed()`，不使用 `@@species` 且始终返回一个新的 `Array` 基类实例。

语法
--


```js
Array[Symbol.species]
```

### 返回值

`get @@species` 被调用的构造函数 (`this`) 的值。该返回值用于构造创建新数组的数组方法的返回值。

描述
--

`@@species` 访问器属性返回 `Array` 对象的默认构造函数。子类的构造函数可能会覆盖并改变构造函数的赋值。默认实现基本上是这样的：


```js
// 以下是一个用于说明的假设底层实现
class Array {
  static get [Symbol.species]() {
    return this;
  }
}
```


由于这种多态实现，派生子类的 `@@species` 默认情况下也会返回构造函数本身。


```js
class SubArray extends Array {}
SubArray[Symbol.species] === SubArray; // true
```


调用不会改变现有数组但会返回新数组实例的数组方法时（例如 `filter()` 和 `map()`），将访问数组的 `constructor[@@species]`。返回的构造函数将用于构造数组方法的返回值。这使得在技术上使数组方法返回与数组无关的对象成为可能。


```js
class NotAnArray {
  constructor(length) {
    this.length = length;
  }
}

const arr = [0, 1, 2];
arr.constructor = { [Symbol.species]: NotAnArray };
arr.map((i) => i); // NotAnArray { '0': 0, '1': 1, '2': 2, length: 3 }
arr.filter((i) => i); // NotAnArray { '0': 1, '1': 2, length: 0 }
arr.concat([1, 2]); // NotAnArray { '0': 0, '1': 1, '2': 2, '3': 1, '4': 2, length: 5 }
```

示例
--

### 普通对象中的 species

`@@species` 属性返回默认构造函数，对于 `Array` 来说，它就是 `Array` 构造函数。


```js
Array[Symbol.species]; // [Function: Array]
```

### 派生对象中的 species

在自定义 `Array` 子类的实例中（例如 `MyArray`），`MyArray` 的 species 是 `MyArray` 构造函数。不过，你可能想要重写这个方法，以便在派生类方法中返回父级 `Array` 对象：


```js
class MyArray extends Array {
  // 重写 MyArray 的 species 属性到父类 Array 的构造函数
  static get [Symbol.species]() {
    return Array;
  }
}
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-array-@@species |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `Array[Symbol.species]` 的 Polyfill 和 `core-js` 中所有受影响的 `Array` 方法对 `Symbol.species` 的支持
* 索引集合类
* `Array`
* `Symbol.species`
Array.prototype.indexOf()
=========================

**`indexOf()`** 方法返回数组中第一次出现给定元素的下标，如果不存在则返回 -1。

尝试一下
----

语法
--


```js
indexOf(searchElement)
indexOf(searchElement, fromIndex)
```

### 参数

`searchElement`

数组中要查找的元素。

`fromIndex` 可选

开始搜索的索引（从零开始），会转换为整数。

* 负索引从数组末尾开始计数——如果 `frommindex < 0`，使用 `frommindex + array.length`。注意，在这种情况下，仍然从前到后搜索数组。
* 如果 `fromIndex < -array.length` 或者省略了 `fromIndex` ，将使用 `0`，而导致整个数组被搜索。
* 如果 `fromIndex >= array.length`，数组不会继续搜索并返回 `-1`。

### 返回值

首个被找到的元素在数组中的索引位置; 若没有找到则返回 **-1**。

描述
--

`indexOf()` 使用严格相等（与 `===` 运算符使用的算法相同）将 `searchElement` 与数组中的元素进行比较。`NaN` 值永远不会被比较为相等，因此当 `searchElement` 为 `NaN` 时 `indexOf()` 总是返回 `-1`。

`indexOf()` 方法会跳过稀疏数组中的空槽。

`indexOf()` 方法是通用的。它只期望 `this` 值具有 `length` 属性和整数键属性。

示例
--

### 使用 indexOf()

以下例子使用 `indexOf()` 方法确定多个值在数组中的位置。


```js
const array = [2, 9, 9];
array.indexOf(2); // 0
array.indexOf(7); // -1
array.indexOf(9, 2); // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -3); // 0
```


你没法使用 `indexOf()` 来搜索 `NaN`。


```js
const array = [NaN];
array.indexOf(NaN); // -1
```

### 找出指定元素出现的所有位置


```js
const indices = [];
const array = ["a", "b", "a", "c", "a", "d"];
const element = "a";
let idx = array.indexOf(element);
while (idx !== -1) {
  indices.push(idx);
  idx = array.indexOf(element, idx + 1);
}
console.log(indices);
// [0, 2, 4]
```

### 判断一个元素是否在数组里，不在则更新数组


```js
function updateVegetablesCollection(veggies, veggie) {
  if (veggies.indexOf(veggie) === -1) {
    veggies.push(veggie);
    console.log(`New veggies collection is: ${veggies}`);
  } else {
    console.log(`${veggie} already exists in the veggies collection.`);
  }
}

const veggies = ["potato", "tomato", "chillies", "green-pepper"];

updateVegetablesCollection(veggies, "spinach");
// New veggies collection is: potato,tomato,chillies,green-pepper,spinach
updateVegetablesCollection(veggies, "spinach");
// spinach already exists in the veggies collection.
```

### 在稀疏数组中使用 indexOf()

不能使用 `indexOf()` 在稀疏数组中搜索空槽。


```js
console.log([1, , 3].indexOf(undefined)); // -1
```

### 在非数组对象上调用 indexOf()

`indexOf()` 方法读取 `this` 的 `length` 属性，然后访问每个整数索引。


```js
const arrayLike = {
  length: 3,
  0: 2,
  1: 3,
  2: 4,
};
console.log(Array.prototype.indexOf.call(arrayLike, 2));
// 0
console.log(Array.prototype.indexOf.call(arrayLike, 5));
// -1
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-array.prototype.indexof |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Array.prototype.indexOf` 的 polyfill
* 索引集合类
* `Array`
* `Array.prototype.findIndex()`
* `Array.prototype.findLastIndex()`
* `Array.prototype.lastIndexOf()`
* `TypedArray.prototype.indexOf()`
* `String.prototype.indexOf()`
Array.prototype.findIndex()
===========================

**`findIndex()`** 方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回 -1。

另请参阅 `find()` 方法，它返回满足测试函数的第一个元素（而不是它的索引）。

尝试一下
----

语法
--


```js
findIndex(callbackFn)
findIndex(callbackFn, thisArg)
```

### 参数

`callbackFn`

为数组中的每个元素执行的函数。它应该返回一个真值以指示已找到匹配元素，否则返回一个假值。该函数被调用时将传入以下参数：

`element`

数组中当前正在处理的元素。

`index`

正在处理的元素在数组中的索引。

`array`

调用了 `findIndex()` 的数组本身。


`thisArg` 可选

执行 `callbackFn` 时用作 `this` 的值。参见迭代方法。

### 返回值

数组中第一个满足测试条件的元素的索引。否则返回 `-1`。

描述
--

`findIndex()` 是一种迭代方法。它按照索引升序依次遍历数组中的每个元素，并调用提供的 `callbackFn` 函数，直到 `callbackFn` 返回一个真值。然后 `findIndex()` 返回该元素的索引并停止遍历数组。如果 `callbackFn` 从未返回一个真值，则 `findIndex()` 返回 `-1`。

`callbackFn` 被调用来处理数组的*每一个*索引，而不仅仅是那些有值的索引。在稀疏数组中，未赋值的空槽与 `undefined` 表现相同。

`findIndex()` 不会改变被调用的数组，但是提供给 `callbackFn` 的函数可能会改变它。但需要注意的是，在第一次调用 `callbackFn` *之前*，数组的长度会被保存。因此：

* 当调用 `findIndex()` 时，`callbackFn` 不会访问超出数组初始长度的任何元素。
* 对已经访问过的索引的更改不会导致再次在这些元素上调用 `callbackFn`。
* 如果 `callbackFn` 改变了数组中已存在但尚未被访问的元素，则传递给 `callbackFn` 的该元素的值将是该元素在被访问时的值。被删除的元素被视为 `undefined`。

**警告：** 上述类型的并发修改经常导致难以理解的代码，通常应避免（特殊情况除外）。

`findIndex()` 方法是通用的。它只期望 `this` 值具有 `length` 属性和整数键属性。

示例
--

### 寻找数组中的首个素数的索引

以下示例返回数组中第一个素数的索引，如果没有素数则返回 `-1`。


```js
function isPrime(element) {
  if (element % 2 === 0 || element < 2) {
    return false;
  }
  for (let factor = 3; factor <= Math.sqrt(element); factor += 2) {
    if (element % factor === 0) {
      return false;
    }
  }
  return true;
}

console.log([4, 6, 8, 9, 12].findIndex(isPrime)); // -1，没有找到
console.log([4, 6, 7, 9, 12].findIndex(isPrime)); // 2（array[2] 是 7）
```

### 在稀疏数组上使用 findIndex()

你可以搜索稀疏数组中的 `undefined` 并来获取空槽的索引。


```js
console.log([1, , 3].findIndex((x) => x === undefined)); // 1
```

### 在非数组对象上调用 findIndex()

`findIndex()` 方法读取 `this` 的 `length` 属性，并访问每个整数索引。


```js
const arrayLike = {
  length: 3,
  0: 2,
  1: 7.3,
  2: 4,
};
console.log(
  Array.prototype.findIndex.call(arrayLike, (x) => !Number.isInteger(x)),
); // 1
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-array.prototype.findindex |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Array.prototype.findIndex` 的 polyfill
* 索引集合类
* `Array`
* `Array.prototype.find()`
* `Array.prototype.findLast()`
* `Array.prototype.findLastIndex()`
* `Array.prototype.indexOf()`
* `Array.prototype.lastIndexOf()`
* `TypedArray.prototype.findIndex()`
Array：length
============

**`length`** 是 `Array` 的实例属性，表示该数组中元素的个数。该值是一个无符号 32 位整数，并且其数值总是大于数组最大索引。

尝试一下
----

值
-

一个小于 232 的非负整数。

| `Array：length` 的属性特性 |
| --- |
| 可写 | 是 |
| 可枚举 | 否 |
| 可配置 | 否 |

描述
--

`length` 属性的值是一个小于 232 的非负整数


```js
const listA = [1, 2, 3];
const listB = new Array(6);

console.log(listA.length);
// 3

console.log(listB.length);
// 6

listB.length = 2 \*\* 32; // 4294967296
// RangeError: Invalid array length

const listC = new Array(-100); // 负数是不允许的
// RangeError: Invalid array length
```


数组对象会观察 `length` 属性，并自动将 `length` 值与数组的内容同步。这意味着：

* 设置 `length` 小于当前长度的值将会截断数组——超过新 `length` 的元素将被删除。
* 设置超过当前 `length` 的任何数组索引（小于 232 的非负整数）将会扩展数组——`length` 属性增加以反映新的最高索引。
* 将 `length` 设置为无效值（例如负数或非整数）会引发 `RangeError` 异常。

当 `length` 被设置为比当前长度更大的值时，数组通过添加空槽来扩展，而不是实际的 `undefined` 值。空槽与数组方法有一些特殊的交互作用；详见数组方法和空槽。


```js
const arr = [1, 2];
console.log(arr);
// [ 1, 2 ]

arr.length = 5; // 将数组长度设置为 5，而当前为 2。
console.log(arr);
// [ 1, 2, <3 empty items> ]

arr.forEach((element) => console.log(element));
// 1
// 2
```


另请参阅：`length` 与数值属性的关系。

示例
--

### 遍历数组

在下面的示例中，通过查看 `length` 属性来遍历数组 `numbers`。然后将每个元素中的值加倍。


```js
const numbers = [1, 2, 3, 4, 5];
const length = numbers.length;
for (let i = 0; i < length; i++) {
  numbers[i] \*= 2;
}
// 遍历后的结果 [2, 4, 6, 8, 10]
```

### 截断数组

在下面的示例中，如果当前长度大于 3，数组 `numbers` 将会缩短为 3。


```js
const numbers = [1, 2, 3, 4, 5];

if (numbers.length > 3) {
  numbers.length = 3;
}

console.log(numbers); // [1, 2, 3]
console.log(numbers.length); // 3
console.log(numbers[3]); // undefined；多余的元素会被删除
```

### 创建固定长度的空数组

将 `length` 设置为大于当前长度的值将会创建一个稀疏数组。


```js
const numbers = [];
numbers.length = 3;
console.log(numbers); // [empty x 3]
```

### 长度不可写的数组

当添加的元素超过当前长度时，数组会自动更新 `length` 属性。如果 `length` 属性设置为不可写，则数组将无法更新它。在严格模式中这会导致错误。


```js
"use strict";

const numbers = [1, 2, 3, 4, 5];
Object.defineProperty(numbers, "length", { writable: false });
numbers[5] = 6; // TypeError: Cannot assign to read only property 'length' of object '[object Array]'
numbers.push(5); // // TypeError: Cannot assign to read only property 'length' of object '[object Array]'
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-properties-of-array-instances-length |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 索引集合类
* `Array`
* `TypedArray`：`length`
* `String`: `length`
* RangeError: invalid array length
Array.prototype.reverse()
=========================

**`reverse()`** 方法*就地*反转数组中的元素，并返回同一数组的引用。数组的第一个元素会变成最后一个，数组的最后一个元素变成第一个。换句话说，数组中的元素顺序将被翻转，变为与之前相反的方向。

要在不改变原始数组的情况下反转数组中的元素，使用 `toReversed()`。

尝试一下
----

语法
--


```js
reverse()
```

### 返回值

原始数组反转后的引用。注意，数组是*就地*反转的，并且没有复制。

描述
--

`reverse` 方法反转数组中元素的位置，改变了数组，并返回该数组的引用。

`reverse()` 方法会保留空槽。如果源数组是稀疏的，则空槽对应的新索引将被删除，并且也成为空槽。

`reverse()` 方法是通用的。它只期望 `this` 值具有 `length` 属性和整数键属性。虽然字符串也是类似于数组的，但这个方法不适用于它们，因为字符串是不可变的。

示例
--

### 反转数组中的元素

下面的示例创建一个数组 `items`，其中包含三个元素，然后反转数组。调用 `reverse()` 会返回反转后的数组 `items` 的引用。


```js
const items = [1, 2, 3];
console.log(items); // [1, 2, 3]

items.reverse();
console.log(items); // [3, 2, 1]
```

### reverse() 方法返回对同一数组的引用

`reverse()` 方法返回对原始数组的引用，因此改变返回的数组也会改变原始数组。


```js
const numbers = [3, 2, 4, 1, 5];
const reversed = numbers.reverse();
// numbers 和 reversed 的顺序都是颠倒的 [5, 1, 4, 2, 3]
reversed[0] = 5;
console.log(numbers[0]); // 5
```


如果你希望 `reverse()` 不改变原始数组，但返回一个浅拷贝数组，就像其他数组方法（例如 `map()`）一样，使用 `toReversed()` 方法。或者，你可以在调用 `reverse()` 之前做一个浅拷贝，使用展开语法或 `Array.from()`。


```js
const numbers = [3, 2, 4, 1, 5];
// [...numbers] 创建一个浅拷贝，因此 reverse() 不会改变原始数据
const reverted = [...numbers].reverse();
reverted[0] = 5;
console.log(numbers[0]); // 3
```

### 对稀疏数组使用 reverse()

调用 `reverse()` 后，稀疏数组保持稀疏状态。空槽将以空槽的形式被复制到它们各自的新索引中。


```js
console.log([1, , 3].reverse()); // [3, empty, 1]
console.log([1, , 3, 4].reverse()); // [4, 3, empty, 1]
```

### 对非数组对象调用 reverse()

`reverse()` 方法读取 `this` 的 `length` 属性。然后，它访问 `0` 和 `length / 2` 之间的每个索引，并交换两端对应的两个索引，并在必要时，删除某些属性。


```js
const arrayLike = {
  length: 3,
  unrelated: "foo",
  2: 4,
};
console.log(Array.prototype.reverse.call(arrayLike));
// { '0': 4, length: 3, unrelated: 'foo' }
// 索引“2”被删除了，因为原本的数据中索引“0”不存在了
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-array.prototype.reverse |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Array.prototype.reverse` 的 polyfill
* 索引集合类
* `Array`
* `Array.prototype.join()`
* `Array.prototype.sort()`
* `Array.prototype.toReversed()`
* `TypedArray.prototype.reverse()`