es5、es6数组API总结

ES5数组方法

  1. 转换方法—toLocaleString()方法、toString()方法、valueOf()方法
  2. 栈方法——push()方法、pop()方法
  3. 队列方法——shift()方法、unshift()方法
  4. 重排序方法——reverse()方法、sort()方法
  5. 操作方法——concat()方法、slice()方法、splice()方法
  6. 位置方法——indexOf()方法、lastIndexOf()方法
  7. 迭代方法——every()方法、filter()方法、forEach()方法、map()方法、some()方法
  8. 归并方法——reduce()方法、reduceRight()方法

转换方法

  1. toString()方法返回由数组中每个值的字符串形式拼接并且以逗号相隔的字符串
  2. valueOf()方法返回的还是数组
  3. toLocaleString()方法也会返回一个数组值以逗号相隔的字符串,但与toString()方法不同的是在返回日期对象时格式不同。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var colors=["red","blue","green"];
    console.log(colors.toString()); //"red,blue,green"
    console.log(colors.valueOf()); //red,blue,green
    console.log(colors.toLocaleString()); //"red,blue,green"

    //toLocaleString()方法与toString()方法在返回日期对象时格式不同
    var today=new Date();
    console.log(today.toString()); // Sun Mar 05 2017 12:57:11 GMT+0800 (中国标准时间)
    console.log(today.toLocaleString()); // 2017/3/5 下午12:57:11

栈方法

  1. push()方法可以接受任意数量的参数,逐个添加到数组末尾,返回修改后数组的长度
  2. pop()方法从数组末尾移除最后一项,返回被移除的项
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var arr=new Array();    //使用构造函数创建数组
    var count=arr.push("red","blue"); //push()返回数组长度

    console.log("count="+count); //count=2
    console.log(arr); //red,blue

    count=arr.push("black"); //count=3

    var item=arr.pop();
    console.log("item="+item);//pop返回被移除的项 item=black

队列方法

  1. shift()方法移除数组的第一次项并返回该项
  2. unshift()方法在数组前端添加任意项,并返回新数组的长度
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var colors=new Array();    //创建数组
    var count=colors.unshift("red","green"); //在数组前端添加两项
    console.log(count); //2

    count=colors.unshift("black"); //此时数组各项顺序为"black","red","green"
    console.log(count) //3

    item=colors.shift();
    console.log(item); //black

栈方法队列方法可知,在这两种方法中添加数组项的方法返回新数组的长度,移除数组项的方法返回被移除项

重排序方法

  1. reverse()方法可以反转数组项的顺序
  2. sort()方法对数组进行升序排序,但sort()方法会调用每个数组项的toString()转型方法,所以sort()方法比较的是字符串,所以为了能正确排序,要将一个排序函数作为参数传给sort()方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//reverse()方法
var values=[0,1,5,10,15];
values.reverse();
console.log(values); //15,10,5,1,0

//无参数sort()方法
values.sort();
console.log(values); //0,1,10,15,5

//将比较函数作为参数传给sort()方法
//此比较函数用于数值类型或者其valueOf()方法会返回数值类型的对象类型
function compare(value1,value2){
return value1-value2; //升序,若要降序则return value2-value1;
}
values.sort(compare);
console.log(values); //0,1,5,10,15

//使用另外一种比较函数一样可以解决,并适用于大多数数据类型
function compare2(value1,value2){
if(value1<value2){
return -1;
}
else if(value1>value2){
return 1;
}
else{
return 0;
}
}
values.sort(compare2);
console.log(values); //0,1,5,10,15
//用字符串数据类型检验
var colors=["red","blue","green","black"];
colors.sort(compare2);
console.log(colors); //black,blue,green,red

colors.sort(compare);
cosole.log(colors); //返回原函数,不进行排序

操作方法

  1. concat()方法用于连接两个或多个数组,不改变现有数组,只是返回被连接数组的一个副本
  2. slice()方法能基于当前数组中的一个或多个项创建一个数组,接受一个或两个参数,即返回项的开始跟结束位置
  3. splice()方法,(返回数组)使用这种方法的方式有三种,如下:

若要删除的项数为0,则返回空数组;若不为0,则返回由被移除项所组成的数组

删除:可以删除任意数量的项,只需指定两个参数,要删除的第一项和要删除的项数
插入:可以向指定位置插入任意数量的项:只需指定三个参数,起始位置、0(要删除的项数)、要插入的项
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定三个参数,起始位置、要删除的项数和要插入的任意数量的项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//删除
var colors=["red","green","blue"];
var removed=colors.splice(0,1); //删除colors数组0的位置的项
console.log(colors); //green,blue
console.log(removed); //red,返回数组只包含一项

//插入
removed=colors.splice(1,0,"yellow","orange"); //从colors数组1的位置插入两项
console.log(colors); //green,yellow,orange,blue
cosole.log(removed); //因为删除项数为0,所以返回空数组

//替换
removed=colors.splice(1,1,"red","purple"); //删除colors数组1的位置的项,并在此插入两项
console.log(colors); //green,red,purple,orange,blue

位置方法

indexOf()方法跟lastIndexOf()方法都接受两个参数,要查找的项跟查找起点位置的索引(可选)。
其中indexOf()方法从开头(索引为0)的位置往后找,
而lastIndexOf()方法从末尾开始向前找。
在比较第一个参数与数组中的每一项时是使用全等操作符进行严格比较的,若没有找到则返回-1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var numbers = [1,2,3,4,5,4,3,2,1];

console.log(numbers.indexOf(4)); //3 已知值从开始查找返回下标
console.log(numbers.lastIndexOf(4)); //5 已知值从尾部开始查找返回下标(下标是从开始算起的)

console.log(numbers.indexOf(4,4)); //5 indexOf(item, start)
console.log(numbers.lastIndexOf(4,4)); //3

var person = { name: "Nicholas" };
var people = [{ name: "Nicholas" }];

var morePeople = [person];

console.log(people.indexOf(person)); //-1
console.log(morePeople.indexOf(person)); //0

console.log(morePeople);

迭代方法

ECMAScript 5
为数组定义了五个迭代方法,每种方法接受两个参数,要在每一项上运行的函数跟运行该函数的作用对象–影响this的值(可选),而传入这些方法的函数要接收三个参数:数组项的值,该项在数组中的位置和数组对象本身。

  1. every()方法对数组中的每一项运行给定的函数,如果该函数对一项都返回true,则返回true。(相当于逻辑与)
  2. filter()方法对数组中的每一项运行给定的函数,返回该函数会返回true的项组成的数组。
  3. forEach()方法对数组中的每一项运行给定的函数,没有返回值。
  4. map()方法对数组中的每一项运行给定的函数,返回每次函数调用的结果组成的数组。
  5. some()方法对数组中的每一项运行给定的函数,如果该函数对一项返回true,则返回true。(相当于逻辑或)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var numbers = [1,2,3,4,5,4,3,2,1];

var everyResult = numbers.every(function(item, index, array) {
return (item>2);
})
console.log(everyResult); // false

var filterResult = numbers.filter(function(item, index, array) {
return (item>2);
})
console.log(filterResult); // 3,4,5,4,3

var forEachResult = numbers.forEach(function(item, index, array) {
//执行具体操作,无返回值
})

var mapResult = numbers.map(function(item, index, array) {
return item*2;
})
console.log(mapResult); // 2,4,6,8,10,8,6,4,2

var someResult = numbers.some(function(item, index, array) {
return (item>2);
})
console.log(someResult); // true

归并方法

ECMAScript5新增了两个归并数组的方法:reduce()和reduceRight()方法,这两个方法都会迭代数组的所有项,构建一个最终返回的值。
这两个方法接收两个参数:一个在每一项上调用的函数和(可选)作为归并 基础的初始值。
而作为参数的函数接收四个参数:前一个值、当前值、项的索引值、数组对象,并且这个函数的任何返回值都会作为该函数的第一个参数自动传给下一项。

1
2
3
4
5
var numbers = [1,2,3,4,5];
var sum = numbers.reduce(function(pre, cur, index, array) {
return pre + cur;
});
console.log(sum); // 15

而reduceRight()方法的作用类似,只是方向相反,具体看下面例子:

1
2
3
4
5
var numbers = [1,2,3,4,5];
var sum = numbers.reduceRight(function(pre, cur, index, array) {
return pre + cur;
});
console.log(sum); // 15

ES6数组方法

扩展运算符,该运算符主要用于函数调用

1
2
3
4
5
6
7
8
9
10
function push(array, ...items) {
array.push(...items);
}

function add(x, y) {
return x + y;
}

const numbers = [4, 38];
add(...numbers) // 42

由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了。

1
2
3
4
5
6
7
8
9
10
11
12
13
// ES5 的写法
function f(x, y, z) {
// ...
}
var args = [0, 1, 2];
f.apply(null, args);

// ES6的写法
function f(x, y, z) {
// ...
}
let args = [0, 1, 2];
f(...args);

下面是扩展运算符取代apply方法的一个实际的例子,应用Math.max方法,简化求出一个数组最大元素的写法。

1
2
3
4
5
6
7
8
// ES5 的写法
Math.max.apply(null, [14, 3, 77])

// ES6 的写法
Math.max(...[14, 3, 77])

// 等同于
Math.max(14, 3, 77);

另一个例子是通过push函数,将一个数组添加到另一个数组的尾部。

1
2
3
4
5
6
7
8
9
// ES5的 写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);

// ES6 的写法
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);

扩展应用符的应用

复制数组(克隆数组,修改a2,a1不会改变)

1
2
3
4
5
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;

合并数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]

var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];

// ES5的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]

与解构赋值结合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]

const [first, ...rest] = [];
first // undefined
rest // []

const [first, ...rest] = ["foo"];
first // "foo"
rest // []
// 如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

const [...butLast, last] = [1, 2, 3, 4, 5];
// 报错

const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 报错

Map 和 Set 结构,Generator 函数

扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,比如 Map 结构。

1
2
3
4
5
6
7
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);

let arr = [...map.keys()]; // [1, 2, 3]

Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。

1
2
3
4
5
6
7
const go = function*(){
yield 1;
yield 2;
yield 3;
};

[...go()] // [1, 2, 3]

上面代码中,变量go是一个 Generator 函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行扩展运算符,就会将内部遍历得到的值,转为一个数组。

如果对没有 Iterator 接口的对象,使用扩展运算符,将会报错。

1
2
const obj = {a: 1, b: 2};
let arr = [...obj]; // TypeError: Cannot spread non-iterable object

Array.from() 类数组转换成数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//类数组对象
let obj = {
0:'hello',
1:'world',
4:'outof bounds data',
length:3 //因为length不能动态改变,随意赋值,最后得到的数组长度就是其值
}
Array.from(obj);
// ["hello", "world", undefined]
//根据属性名对应到数组的index,超过length部分舍弃。没有对应的属性,置为undefined

/实现了Iterator接口的数据结构
let str = 'babe';
Array.from(str);
// ["b", "a", "b", "e"]
[...str]
// ["b", "a", "b", "e"]

注意:
Array.from()是一个很不严谨的角色,只要对象含有length属性,且值为正整数就能转
不保证转出来的东西质量是否符合要求。
Array.from({user:'babe',length:5})
// [undefined, undefined, undefined, undefined, undefined]

Array.from()可接收第二个参数,用于对数组的每一项进行处理并返回
Array.from([1,2,3],x=>x*x)
// [1, 4, 9]

Array.from([1,2,3],x=>{x*x})
//[undefined, undefined, undefined] --切记处理函数中一定要返回

Array.from()还可接收第三个参数,这样在处理函数中就可以使用传进去的对象域中的值
let that = {
user:'babe'
}
let obj = {
0:'babe',
1:'zhangsan',
2:'lisi',
length:3
}
let result = Array.from(obj,(user) =>{
if(user == that.user){
return user;
}

return 0;
},that);
result //["babe", 0, 0]

Array.of()

此方法用于将一组值,转换为数组。这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。

1
2
3
4
5
6
7
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]

Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一。

1
2
3
4
Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]

Array.copyWithin()

数组实例的 在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。
它接受三个参数。

  1. target(必需):从该位置开始替换数据。
  2. start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。
  3. end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]

// 将3号位复制到0号位
[].copyWithin.call({length: 5, 3: 1}, 0, 3)
// {0: 1, 3: 1, length: 5} 此处有疑惑

// 将2号位到数组结束,复制到0号位
let i32a = new Int32Array([1, 2, 3, 4, 5]);
i32a.copyWithin(0, 2);
// Int32Array [3, 4, 5, 4, 5]

// 对于没有部署 TypedArray 的 copyWithin 方法的平台
// 需要采用下面的写法
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4, 2, 3, 4, 5]

Array.find()

数组实例的 用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。

1
2
3
4
5
6
let arr = [1, 4, -5, 10]
console.log(arr.find((n) => n < 0)) // -5

[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10

上面代码中,find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。

Array.findIndex()

数组实例的findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

1
2
3
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2

Array.fill()

数组实例的方法使用给定值,填充一个数组。

1
2
3
4
5
['a', 'b', 'c'].fill(7)
// [7, 7, 7]

new Array(3).fill(7)
// [7, 7, 7]

上面代码表明,fill方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。

fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。

1
2
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']

entries(),keys() 和 values()

ES6 提供三个新的方法——entries(),keys()和values()——用于遍历数组。它们都返回一个遍历器对象,可以用for…of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let arr = ['a', 'b']
for (let index of arr.keys()) {
console.log(index);
}
// 0
// 1

for (let elem of arr.values()) {
console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of arr.entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"

如果不使用for…of循环,可以手动调用遍历器对象的next方法,进行遍历。

1
2
3
4
5
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']

Array.includes()

数组实例的 方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。ES2016 引入了该方法。

1
2
3
[1, 2, 3].includes(2)     // true
[1, 2, 3].includes(4) // false
[1, 2, NaN].includes(NaN) // true

indexOf方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN的误判。

1
2
3
4
[NaN].indexOf(NaN)
// -1
[NaN].includes(NaN)
// true

另外,Map 和 Set 数据结构有一个has方法,需要注意与includes区分。

Map 结构的has方法,是用来查找键名的,比如Map.prototype.has(key)、WeakMap.prototype.has(key)、Reflect.has(target, propertyKey)。
Set 结构的has方法,是用来查找值的,比如Set.prototype.has(value)、WeakSet.prototype.has(value)。

数组的空位指

数组的某一个位置没有任何值。比如,Array构造函数返回的数组都是空位。

Buy me a cup of coffee,thanks!