一、forEach()、map()、filter()、every()、some()
1、都带一个被称为迭代方法的回调函数(callback),因为他们以某种方式迭代整个数组。
2、都有一个可选的参数thisObject,如果提供了这个参数,thisObject变成回调函数内部的this关键字的值。如果没有提供,例如函数在一个显示的对象上下文外被调用时,this将引用全局对象window
3、实际在调用回调函数时传入了3个参数。第一个是当前元素项的值,第二个是它在数组中的索引,第三个是数组本身的一个引用。
二、JavaScript函数忽略任何没有在参数列表中命名的参数,因此提供一个只有一个参数的回调函数是安全的,例如alert。

⭐️数组方法

方法 是否改变原数组
(是:√,否:×)
返回 描述 示例
concat() × 新数组 合并。连接两个数组并返回一个新的数组。 var myArray = new Array(‘1’, ‘2’, ‘3’)
myArray = myArray.concat(‘a’, ‘b’, ‘c’)
console.log(myArray) // [‘1’, ‘2’, ‘3’, ‘a’, ‘b’, ‘c’]
join(deliminator=’,’)
将数组的所有元素连接成一个字符串 var myArray = new Array(‘Wind’, ‘Rain’, ‘Fire’)
var list = myArray.join(‘ - ‘)
console.log(list) // ‘Wind - Rain - Fire’
push()
(添加元素后的数组)
返回数组操作后的长度 在数组末尾添加一个或多个元素,并返回数组操作后的长度 var myArray = new Array(‘1’, ‘2’)
myArray.push(‘3’)
// console.log(myArray) // [‘1’, ‘2’, ‘3’]
pop()
(删除最后一项后的数组)
返回数组的最后一个元素 从数组移出最后一个元素,并返回该元素 var myArray = new Array(‘1’, ‘2’, ‘3’)
var last = myArray.pop()
console.log(myArray) // [‘1’, ‘2’]
console.log(last) // ‘3’
unshift()
(添加元素后的数组)
返回数组操作后的长度 在数组开头添加一个或多个元素,并返回数组的新长度 var myArray = new Array(‘1’, ‘2’, ‘3’)
myArray.unshift(‘4’, ‘5’)
console.log(myArray) // [‘4’, ‘5’, ‘1’, ‘2’, ‘3’]
shift()
(删除第一项后的数组)
返回数组的第一个元素 从数组移出第一个元素,并返回该元素 var myArray = new Array(‘1’, ‘2’, ‘3’)
var first = myArray.shift()
console.log(myArray) // [‘2’, ‘3’]
console.log(first) // ‘1’
slice(start_index, upto_index) × 返回从索引start到end(不包括end)的新数组 从数组提取一个片段,并作为一个新数组返回 var myArray = new Array(‘a’, ‘b’, ‘c’, ‘d’, ‘e’)
myArray = myArray.slice(1, 4) // 包含索引1,不包括索引4
console.log(myArray) // [‘b’, ‘c’, ‘d’]
splice(index, count_to_remove, addElement1, addElement2, …)
(添加、删除、插入元素后的数组)
返回已被删除元素的数组 从数组移出一些元素,(可选)并替换它们 var myArray = new Array(‘1’, ‘2’, ‘3’, ‘4’, ‘5’)
myArray.splice(1, 3, ‘a’, ‘b’, ‘c’, ‘d’) // 从数组下标为1的地方移除3个元素,然后插入新的元素
console.log(myArray) // [‘1’, ‘a’, ‘b’, ‘c’, ‘d’, ‘5’]
reverse() 反转。颠倒数组元素的顺序:第一个变成最后一个,最后一个变成第一个 var myArray = new Array(‘1’, ‘2’, ‘3’)
myArray.reverse()
console.log(myArray) // [‘3’, ‘2’, ‘1’]
sort()
(排序后的数组)
返回排序后的数组 一、排序。给数组元素排序

二、可以带一个回调函数来决定怎么比较数组元素。这个回调函数比较两个值,并返回3个值中的一个
【实例1】
var myArray = new Array(‘Wind’, ‘Rain’, ‘Fire’)
myArray.sort()
console.log(myArray) // [‘Fire’, ‘Rain’, ‘Wind’]

【实例2】
var sortFn = function(a, b) {
if (a[a.length - 1] < b[b.length -1]) return -1 // 如果a 小于 b,返回-1(或任何负数)
if (a[a.length -1] > b[b.length -1]) return 1
// 如果a 大于 b,返回1(或任何正数)
if (a[a.length -1] == b[b.length - 1]) return 0
// 如果a和b相等,返回0
}
myArray.sort(sortFn)
console.log(myArray) // [‘Wind’, ‘Fire’, ‘Rain’]
indexOf(searchElement[, fromIndex])
在数组中搜索searchElement并返回第一个匹配的索引 var a = [‘a’, ‘b’, ‘a’, ‘b’, ‘a’]
console.log(a.indexOf(‘b’)) // 1
console.log(a.indexOf(‘b’, 2)) // 3
console.log(a.indexOf(‘z’)) // -1
lastIndexOf(searchElement[, fromIndex])
和indexOf差不多,但这是从结尾开始,并且是反向搜索 var a = [‘a’, ‘b’, ‘c’, ‘d’, ‘a’, ‘b’]
console.log(a.lastIndexOf(‘b’)) // 5
console.log(a.lastIndexOf(‘b’, 4)) // 1
console.log(a.lastIndexOf(‘z’)) // -1
forEach(callback[, thisObject])
在数组每个元素项上执行callback var a = [‘a’, ‘b’, ‘c’]
a.forEach(function(element) {
console.log(element)
})
map(callback[, thisObject]) × 在数组的每个单元项上执行callback函数,并返回包含回调函数返回值的新数组 var a1 = [‘a’, ‘b’, ‘c’]
var a2 = a1.map(function(item) { return item.toUpperCase() })
console.log(a2) // [‘A’, ‘B’, ‘C’]
filter(callback[, thisObject]) × 过滤器。返回一个包含所有在回调函数上返回为true的元素的新数组 var a1 = [‘a’, 10, ‘b’, 20, ‘c’, 30]
var a2 = a1.filter(function(item) { return typeof item == ‘number’ })
console.log(a2) // [10, 20, 30]
every(callback[, thisObject])
当数组中每一个元素在callback上被返回true时就返回true
(判断是不是数组中的所有元素都符合条件,并且返回布尔值)
function isNumber(value) {
return typeof value == ‘number’
}
var a1 = [1, 2, 3]
console.log(a1.every(isNumber)) // true
var a2 = [1, ‘2’, 3]
console.log(a2.every(isNumber)) // false
some(callback[, thisObject])
只要数组中有一项在callback上被返回true,就返回true
(判断数组中只要有符合条件的就返回true)
function isNumber(value) {
return typeof value == ‘number’
}
var a1 = [1, 2, 3]
console.log(a1.some(isNumber)) // true
var a2 = [1, ‘2’, 3]
console.log(a2.some(isNumber)) // true
var a3 = [‘1’, ‘2’, ‘3’]
console.log(a3.some(isNumber)) // false
reduce(callback[, initialValue])
使用回调函数callback(firstValue, secondValue)把数组列表计算成一个单一值 var a = [10, 20, 30]
var total = a.reduce(function(first, second) {
return first + second
}, 0)
console.log(total) // 60
reduceRight(callback[, initalValue])
和reduce()相似,但这从最后一个元素开始
isArray()

【见】数组方法 - 图1

添加/移除数组元素

【见】添加/移除数组元素

遍历数组(interating over array)

一、遍历数组元素以某种方式处理每个元素是一个常见的操作

数组方法

forEach:arr.forEach(推荐)

一、arr.forEach方法允许为数组的每个元素都运行一个函数
二、语法

  1. arr.forEach(function(item, index, array) {
  2. // ... do something with item
  3. });

| 【示例】下面这个程序显示了数组的每个元素:```javascript // 对每个元素调用 alert [“Bilbo”, “Gandalf”, “Nazgul”].forEach(alert); 而这段代码更详细地介绍了它们在目标数组中的位置:

[“Bilbo”, “Gandalf”, “Nazgul”].forEach((item, index, array) => { alert(${item} is at index ${index} in ${array}); });

1、该函数的结果(如果它有返回)会被抛弃和忽略。 |
| --- |

三、在数组定义时省略的元素不会在forEach遍历时被列出,但是手动赋值为undefined的元素是会被列出的。

| 【示例】```javascript
var array = ['first', 'second', , 'fourth'];

array.forEach(function(element, idx) {
  console.log(element);
  console.log('idx: ', idx)
})
// first
// idx: 0
// second
// idx: 1
// fourth
// idx: 3

if(array[2] === undefined) { console.log('array[2] is undefined'); }
// 'array[2] is undefined'

var array = ['first', 'second', undefined, 'fourth'];

array.forEach(function(element) {
  console.log(element);
})
// first
// second
// undefind
// fourth

if(array[2] === undefined) { console.log('array[2] is undefined'); }
// 'array[2] is undefined'

| | —- |

其他方法

for

一、遍历数组最古老的方式就是for循环:运行得最快,可兼容旧版本浏览器。

| 【示例】```javascript var colors = [‘red’, ‘green’, ‘blue’] for (var i = 0; i < colors.length; i++) { console.log(colors[i]) }

 |
| --- |

1、如果确定数组中没有一个元素的求值是false——如果你的数组只包含DOM节点。以下方式更高效
```javascript
var divs = document.getElementsByTagName('div')
for (var i = 0, div; div = divs[i]; i++) {
    /* process div in some way*/
}

(1)避免了检测数组长度的开销
(2)确保了div变量当前在每次循环中都被重新赋值为当前项。

for..of

一、现代语法,只能访问 items

for (let item of arr)

| 【示例】```javascript let fruits = [“Apple”, “Orange”, “Plum”];

// 遍历数组元素 for (let fruit of fruits) { alert( fruit ); }

 |
| --- |

二、for..of不能获取当前元素的索引,只是获取元素值,但大多数情况是够用的。而且这样写更短。
<a name="BdGjp"></a>
### for...in(不建议使用)
一、技术上来讲,因为数组也是对象,所以使用for..in也是可以的:

| 【示例】```javascript
let arr = ["Apple", "Orange", "Pear"];

for (let key in arr) {
  alert( arr[key] ); // Apple, Orange, Pear
}

| | —- |

二、但是不建议这样做。会有一些潜在问题存在:
1、正常元素和所有可枚举的属性都会被列出。
(1)for..in循环会遍历所有属性,不仅仅是这些数字属性。在浏览器和其它环境中有一种称为“类数组”的对象,它们看似是数组。也就是说,它们有length和索引属性,但是也可能有其它的非数字的属性和方法,这通常是我们不需要的。for..in循环会把它们都列出来。所以如果我们需要处理类数组对象,这些“额外”的属性就会存在问题。
2、for..in循环适用于普通对象,并且做了对应的优化。但是不适用于数组,因此速度要慢 10-100 倍。当然即使是这样也依然非常快。只有在遇到瓶颈时可能会有问题。但是我们仍然应该了解这其中的不同。
三、通常来说,我们不应该用for..in来处理数组。

在数组中搜索

一、在数组中进行搜索的方法。

indexOf/lastIndexOf 和 includes

一、arr.indexOf、arr.lastIndexOf和arr.includes方法与字符串操作具有相同的语法,并且作用基本上也与字符串的方法相同,只不过这里是对数组元素而不是字符进行操作:

  • arr.indexOf(item, from)——从索引from开始搜索item,如果找到则返回索引,否则返回-1。
  • arr.lastIndexOf(item, from)—— 和上面相同,只是从右向左搜索。
  • arr.includes(item, from)—— 从索引from开始搜索item,如果找到则返回true(译注:如果没找到,则返回false)。 | 【示例】```javascript let arr = [1, 0, false];

alert( arr.indexOf(0) ); // 1 alert( arr.indexOf(false) ); // 2 alert( arr.indexOf(null) ); // -1

alert( arr.includes(1) ); // true

 |
| --- |

二、这些方法使用的是严格相等===比较。所以如果我们搜索false,会精确到的是false而不是数字0。<br />三、如果我们想检查是否包含某个元素,并且不想知道确切的索引,那么arr.includes是首选。<br />1、includes的一个非常小的差别是它能正确处理NaN,而不像indexOf/lastIndexOf:

| 【示例】```javascript
const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1(应该为 0,但是严格相等 === equality 对 NaN 无效)
alert( arr.includes(NaN) );// true(这个结果是对的)

| | —- |

find 和 findIndex

一、在对象数组中找到具有特定条件的对象:find、findIndx
二、语法:

let result = arr.find(function(item, index, array) {
  // 如果返回 true,则返回 item 并停止迭代
  // 对于假值(falsy)的情况,则返回 undefined
});

1、依次对数组中的每个元素调用该函数:

  • item是元素。
  • index是它的索引。
  • array是数组本身。

2、如果它返回true,则搜索停止,并返回item。如果没有搜索到,则返回undefined。

| 【示例】我们有一个存储用户的数组,每个用户都有id和name字段。让我们找到id == 1的那个用户:```javascript let users = [ {id: 1, name: “John”}, {id: 2, name: “Pete”}, {id: 3, name: “Mary”} ];

let user = users.find(item => item.id == 1);

alert(user.name); // John

(1)我们传给了find一个单参数函数item => item.id == 1。这很典型,并且find方法的其他参数很少使用。 |
| --- |

三、arr.findIndex方法(与arr.find方法)基本上是一样的,但它返回找到元素的索引,而不是元素本身。并且在未找到任何内容时返回-1。
<a name="aVr5o"></a>
## filter
一、find方法搜索的是使函数返回true的第一个(单个)元素。<br />1、如果需要匹配的有很多,我们可以使用arr.filter(fn)。<br />二、filter语法与find大致相同,但是filter返回的是所有匹配元素组成的数组:
```javascript
let results = arr.filter(function(item, index, array) {
  // 如果 true item 被 push 到 results,迭代继续
  // 如果什么都没找到,则返回空数组
});

| 【示例】```javascript let users = [ {id: 1, name: “John”}, {id: 2, name: “Pete”}, {id: 3, name: “Mary”} ];

// 返回前两个用户的数组 let someUsers = users.filter(item => item.id < 3);

alert(someUsers.length); // 2

 |
| --- |

| 【项目示例】项目中的“列表删除某一项”功能可以用到这个方法```javascript
let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"}
];

// 返回前两个用户的数组
let someUsers = users.filter(item => item.id !== 2);

console.log(someUsers);

[
  {id: 1, name: "John"},
  {id: 3, name: "Mary"}
]

| | —- |

| 【示例】数组对象中的某个对象值不能为xx```javascript if (newData.filter((v) => { return !v.number }).length) { message.error(‘数量不能为0’) return }

 |
| --- |

<a name="ouIdo"></a>
# 转换数组
一、进行数组转换和重新排序的方法。
<a name="YayE7"></a>
## map
一、arr.map方法对数组的每个元素都调用函数,并返回结果数组。<br />二、语法:
```javascript
let result = arr.map(function(item, index, array) {
  // 返回新值而不是当前元素
})

| 【示例】在这里我们将每个元素转换为它的字符串长度:```javascript let lengths = [“Bilbo”, “Gandalf”, “Nazgul”].map(item => item.length); alert(lengths); // 5,7,6

 |
| --- |

<a name="cFf4r"></a>
## sort(fn)
一、arr.sort方法对数组进行原位(in-place)排序,更改元素的顺序。(译注:原位是指在此数组内,而非生成一个新数组。)<br />二、它返回排序后的数组,但是返回值通常会被忽略,因为修改了arr本身。<br />三、语法:`arr.sort()`

| ☆-1【示例】```javascript
let arr = [ 1, 2, 15 ];

// 该方法重新排列 arr 的内容
arr.sort();

alert( arr );  // 1, 15, 2

1、你有没有注意到结果有什么奇怪的地方?
(1)顺序变成了1, 15, 2。不对,但为什么呢?
① 这些元素默认情况下被按字符串进行排序。
② 从字面上看,所有元素都被转换为字符串,然后进行比较。对于字符串,按照词典顺序进行排序,实际上应该是”2” > “15”。 | | —- |

1、要使用我们自己的排序顺序,我们需要提供一个函数作为arr.sort()的参数。

| 【示例】该函数应该比较两个任意值并返回:```javascript function compare(a, b) { if (a > b) return 1; // 如果第一个值比第二个值大 if (a == b) return 0; // 如果两个值相等 if (a < b) return -1; // 如果第一个值比第二个值小 }

 |
| --- |

| ☆-1【示例】按数字进行排序:```javascript
function compareNumeric(a, b) {
  if (a > b) return 1;
  if (a == b) return 0;
  if (a < b) return -1;
}

let arr = [ 1, 2, 15 ];

arr.sort(compareNumeric);

alert(arr);  // 1, 2, 15

1、现在结果符合预期了。 | | —- |

四、arr可以是由任何内容组成的数组,它可能包含数字、字符串、对象或其他任何内容。我们有一组一些元素。要对其进行排序,我们需要一个排序函数来确认如何比较这些元素。默认是按字符串进行排序的。
五、arr.sort(fn)方法实现了通用的排序算法。我们不需要关心它的内部工作原理(大多数情况下都是经过快速排序Timsort算法优化的)。它将遍历数组,使用提供的函数比较其元素并对其重新排序,我们所需要的就是提供执行比较的函数fn。
六、如果我们想知道要比较哪些元素 —— 那么什么都不会阻止 alert 它们:

| ☆-1【示例】```javascript [1, -2, 15, 2, 0, 8].sort(function(a, b) { alert( a + “ <> “ + b ); return a - b; });

1、alert出来的a, b ~~(20210428:a,b的顺序有点搞不明白???以下表格是我自己写的)(20220422:快排+Timsort算法优化)~~<br />2、该算法可以在此过程中,将一个元素与多个其他元素进行比较,但是它会尝试进行尽可能少的比较。 |
| --- |

| a | b | 结果 | 比较的结果 | 数组 |
| --- | --- | --- | --- | --- |
| -2 | 1 | false | -2 < 1 | [-2, 1, 15, 2, 0, 8] |
| 15 | -2 | true | 15 < -2 |  |
| 15 | 1 | true | 15 > 1 |  |
| 2 | 1 | true | 2 > 1 |  |
| 2 | 15 | false | 2 < 15 |  |
| 0 | 2 | false | 0 < 2 |  |
| 0 | 1 | false | 0 < 1 |  |
| 0 | -2 | true | 0 > -2 |  |
| 8 | 1 | true | 8 > 1 |  |
| 8 | 15 | false | 8 < 15 |  |
| 8 | 2 | true | 8 > 2 |  |

七、比较函数可以返回任何数字<br />1、实际上,比较函数只需要返回一个正数表示“大于”,一个负数表示“小于”。

| ☆-1【示例】通过这个原理我们可以编写更短的函数:```javascript
let arr = [ 1, 2, 15 ];

arr.sort(function(a, b) { return a - b; });

alert(arr);  // 1, 2, 15

| | —- |

| ☆-1【示例】这里使用箭头函数会更加简洁:```javascript arr.sort( (a, b) => a - b );

 |
| --- |

八、使用localeComparefor strings<br />1、[字符串比较](https://zh.javascript.info/string#correct-comparisons)算法:默认情况下,它通过字母的代码比较字母。<br />2、对于许多字母,最好使用str.localeCompare方法正确地对字母进行排序,例如Ö。

| 【示例】让我们用德语对几个国家/地区进行排序:```javascript
let countries = ['Österreich', 'Andorra', 'Vietnam'];

alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich(错的)

alert( countries.sort( (a, b) => a.localeCompare(b) ) ); // Andorra,Österreich,Vietnam(对的!)

| | —- |

reverse

一、arr.reverse方法用于颠倒arr中元素的顺序。也会返回颠倒后的数组arr。

| 【示例】```javascript let arr = [1, 2, 3, 4, 5]; arr1 = arr.reverse();

alert( arr ); // 5,4,3,2,1

 |
| --- |

<a name="mClBL"></a>
## split 和 join
一、[str.split(delim)](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference/Global_Objects/String/split)方法通过给定的分隔符delim将字符串分割成一个数组。

| 【示例】我们用“逗号后跟着一个空格”作为分隔符:```javascript
let names = 'Bilbo, Gandalf, Nazgul';

let arr = names.split(', ');

for (let name of arr) {
  alert( `A message to ${name}.` ); // A message to Bilbo(和其他名字)
}

| | —- |

二、语法

  • split方法有一个可选的第二个数字参数 —— 对数组长度的限制。如果提供了,那么额外的元素会被忽略。但实际上它很少使用: | 【示例】```javascript let arr = ‘Bilbo, Gandalf, Nazgul, Saruman’.split(‘, ‘, 2);

alert(arr); // Bilbo, Gandalf

 |
| --- |

三、调用带有空参数s的split(s),会将字符串拆分为字母数组:

| 【示例】```javascript
let str = "test";

alert( str.split('') ); // t,e,s,t

| | —- |

四、arr.join(glue)与split相反。它会在它们之间创建一串由glue粘合的arr项。

| 【示例】```javascript let arr = [‘Bilbo’, ‘Gandalf’, ‘Nazgul’];

let str = arr.join(‘;’); // 使用分号 ; 将数组粘合成字符串

alert( str ); // Bilbo;Gandalf;Nazgul

 |
| --- |

| 【示例】在大数据量场景下,以下哪种js中字符串连接方式较为高效(     )<br />A. a+=b<br />B. a = a+b<br />C. Array.join()<br />D. Array.push()<br />答案:C<br />解析:<br />1、+的处理机制是:新建一个临时字符串,将新字符串赋值为a+b,然后返回这个临新字符串并同时销毁原始字符串,所以字符串连接效率较低。<br />用Array.join()不会新建临时字符串。<br />2、效率<br />- 旧浏览器(ie7-)以下用join会更高效。<br />- 在现代浏览器,尽量用+,更高效。<br />- 在少数现代浏览器中,“+”不一定会比join快(如,safari5.0.5,opera11.10)<br />- 本身是字符串数组的,直接join会更好。<br /> |
| --- |

<a name="FaYWt"></a>
## reduce/reduceRight
一、遍历<br />1、当我们需要遍历一个数组时 —— 我们可以使用forEach,for或for..of。<br />2、当我们需要遍历并返回每个元素的数据时 —— 我们可以使用map。<br />3、arr.reduce方法和arr.reduceRight方法和上面的种类差不多,但稍微复杂一点。它们用于根据数组计算单个值。<br />二、arr.reduce语法:
```javascript
let value = arr.reduce(function(accumulator, item, index, array) {
  // ...
}, [initial]);

1、该函数一个接一个地应用于所有数组元素,并将其结果“搬运(carry on)”到下一个调用。
2、参数:

  • accumulator—— 是上一个函数调用的结果,第一次等于initial(如果提供了initial的话)。
  • item—— 当前的数组元素。
  • index—— 当前索引。
  • arr—— 数组本身。

3、应用函数时,上一个函数调用的结果将作为第一个参数传递给下一个函数。
4、因此,第一个参数本质上是累加器,用于存储所有先前执行的组合结果。最后,它成为reduce的结果。

| ☆-2【示例】我们通过一行代码得到一个数组的总和:```javascript let arr = [1, 2, 3, 4, 5];

let result = arr.reduce((sum, current) => sum + current, 0);

alert(result); // 15

1、传递给reduce的函数仅使用了 2 个参数,通常这就足够了。<br />2、让我们看看细节,到底发生了什么。<br />(1)在第一次运行时,sum的值为初始值initial(reduce的最后一个参数),等于 0,current是第一个数组元素,等于1。所以函数运行的结果是1。<br />(2)在第二次运行时,sum = 1,我们将第二个数组元素(2)与其相加并返回。<br />(3)在第三次运行中,sum = 3,我们继续把下一个元素与其相加,以此类推……<br />3、计算流程:<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/355497/1619575838050-16589f6f-0543-442c-91ee-978118f0e28f.png#clientId=uca368999-21b8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=125&id=baZZO&margin=%5Bobject%20Object%5D&name=image.png&originHeight=125&originWidth=632&originalType=binary&ratio=1&rotation=0&showTitle=false&size=8633&status=done&style=none&taskId=ua8899c00-599b-4e31-8787-9bc4e91a070&title=&width=632)<br />4、或者以表格的形式表示,每一行代表的是对下一个数组元素的函数调用:<br />(1)在这里,我们可以清楚地看到上一个调用的结果如何成为下一个调用的第一个参数。 |
| --- |

|  | sum | current | result |
| --- | --- | --- | --- |
| 第 1 次调用 | 0 | 1 | 1 |
| 第 2 次调用 | 1 | 2 | 3 |
| 第 3 次调用 | 3 | 3 | 6 |
| 第 4 次调用 | 6 | 4 | 10 |
| 第 5 次调用 | 10 | 5 | 15 |

| ☆-2【示例】我们也可以省略初始值:```javascript
let arr = [1, 2, 3, 4, 5];

// 删除 reduce 的初始值(没有 0)
let result = arr.reduce((sum, current) => sum + current);

alert( result ); // 15

(1)结果是一样的。这是因为如果没有初始值,那么reduce会将数组的第一个元素作为初始值,并从第二个元素开始迭代。
(2)计算表与上面相同,只是去掉第一行。
(3)但是这种使用需要非常小心。如果数组为空,那么在没有初始值的情况下调用reduce会导致错误。```javascript let arr = [];

// Error: Reduce of empty array with no initial value // 如果初始值存在,则 reduce 将为空 arr 返回它(即这个初始值)。 arr.reduce((sum, current) => sum + current);

(4)所以建议始终指定初始值。 |
| --- |

| 【示例】二维数组改成一维数组```javascript
const arr = [['test1'], ['test2'], ['test3','test4]];
const lists = arr.reduce((a, b) => a.concat(b), []) // 第二个参数是为了保证当arr为[], 也不会报错:Reduce of empty array with no initial value
console.log(lists); // ['test1', 'test2', 'test3', 'test4']

// 也可以用flat
const lists1 = arr.flat(1);
console.log(lists1); // ['test1', 'test2', 'test3', 'test4']

| | —- |

| 【示例】对象数组分组,合并成二维数组```javascript const data = [ { name: ‘bar’, age: 24, city: ‘hangzhou’ }, { name: ‘fiz’, age: 22, city: ‘shanghai’ }, { name: ‘baz’, age: 19, city: ‘hangzhou’ } ];

function groupBy(key) { const obj = data.reduce((prev, item) => { prev[item[key]] = […prev[item[key]] || [], item] return prev; }, {}) console.log(obj); console.log(Object.values(obj)) return Object.values(obj); }

const test1 = groupBy(‘city’); console.log(test1);

打印出来的值为```javascript
// obj
{
  'hangzhou': [
    { name: 'bar', age: 24, city: 'hangzhou' },
    { name: 'baz', age: 19, city: 'hangzhou' }
  ],
  'shanghai': [
    { name: 'fiz', age: 22, city: 'shanghai' }
  ]
}

// Object.values(obj)
[
  [
    { name: 'bar', age: 24, city: 'hangzhou' },
    { name: 'baz', age: 19, city: 'hangzhou' }
  ],
  [
    { name: 'fiz', age: 22, city: 'shanghai' }
  ]
]

| | —- |

四、arr.reduceRight和arr.reduce方法的功能一样,只是遍历为从右到左。

覆盖数组成员的方法

arr.fill(value, start, end)

一、从索引start到end,用重复的value填充数组。

arr.copyWithin(target, start, end)

一、将从位置start到end的所有元素复制到自身的target位置(覆盖现有元素)。

判断是否是数组类型:Array.isArray

一、数组是基于对象的,不构成单独的语言类型。所以typeof不能帮助从数组中区分出普通对象:
二、有一种特殊的方法用于判断数组:Array.isArray(value)。如果value是一个数组,则返回true;否则返回false。

| 【示例】```javascript alert(Array.isArray({})); // false

alert(Array.isArray([])); // true

 |
| --- |

<a name="n3yKc"></a>
# 大多数方法都支持 “thisArg”
一、几乎所有调用函数的数组方法 —— 比如find,filter,map,除了sort是一个特例,都接受一个可选的附加参数thisArg。<br />二、上面的部分中没有解释该参数,因为该参数很少使用。但是为了完整性,我们需要讲讲它。<br />三、以下是这些方法的完整语法:
```javascript
arr.find(func, thisArg);
arr.filter(func, thisArg);
arr.map(func, thisArg);
// ...
// thisArg 是可选的最后一个参数

四、thisArg参数的值在func中变为this。

| 【示例】在这里我们使用army对象方法作为过滤器,thisArg用于传递上下文(passes the context):```javascript let army = { minAge: 18, maxAge: 27, canJoin(user) { return user.age >= this.minAge && user.age < this.maxAge; } };

let users = [ {age: 16}, {age: 20}, {age: 23}, {age: 30} ];

// 找到 army.canJoin 返回 true 的 user let soldiers = users.filter(army.canJoin, army);

alert(soldiers.length); // 2 alert(soldiers[0].age); // 20 alert(soldiers[1].age); // 23

1、如果在上面的示例中我们使用了users.filter(army.canJoin),那么army.canJoin将被作为独立函数调用,并且这时this=undefined,从而会导致即时错误。<br />2、可以用users.filter(user => army.canJoin(user))替换对users.filter(army.canJoin, army)的调用。前者的使用频率更高,因为对于大多数人来说,它更容易理解。 |
| --- |

<a name="tdorb"></a>
# 检查数组
<a name="xDJoF"></a>
## arr.some(fn) / arr.every(fn)
一、与map类似,对数组的每个元素调用函数fn。如果任何/所有结果为true,则返回true,否则返回false。<br />二、这两个方法的行为类似于||和&&运算符<br />1、如果fn返回一个真值,arr.some()立即返回true并停止迭代其余数组项;<br />2、如果fn返回一个假值,arr.every()立即返回false并停止对其余数组项的迭代。

| 【示例】我们可以使用every来比较数组:```javascript
function arraysEqual(arr1, arr2) {
  return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]);
}

alert( arraysEqual([1, 2], [1, 2])); // true

| | —- |

其他方法

arr.flat(depth)/arr.flatMap(fn)

一、从多维数组创建一个新的扁平数组。

| 【示例】javascript const arr = [1, [2, 3]]; console.log(arr.flat(1)); // [1, 2, 3] | | —- |

Array.of(element0[, element1[, …[, elementN]]])

一、基于可变数量的参数创建一个新的Array实例,而不需要考虑参数的数量或类型。