Js基础系列--数组(Array类型)操作

1,098 阅读8分钟

JavaScript中的数组相关的操作真的是 太重要,太重要,太重要了 ···

本文总结了es5和es6中出现的程序中经常用到的数组操作方法。

创建数组

var arr1 = new Array(3); // [empty × 3] arr1[0]的值undefined
var arr2 = new Array('1', 2); // ["1", 2]
var arr3 = ['green'] // ['green']

检测数组

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

转换方法

['red', 'blue', 'green'].toString(); // 'red', 'blue', 'green'
['red', 'blue', 'green'].valueOf(); // ['red', 'blue', 'green']

toString()方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。

valueOf()返回的还是数组。

栈方法

var colors = new Array();
var count = colors.push('red', 'green'); // 入栈方法,从数组尾部推入值
console.log(count); // 2

var count = colors.push('black');
console.log(count); // 3

var item = colors.pop(); // 出栈方法,从数组尾部取出值
console.log(item); // black
console.log(colors.length); // 2

队列方法

// case 1
var colors = new Array();
var count = colors.push('red', 'green');
var item = colors.shift(); // 出队方法,从数组头部取出值
console.log(colors); // ['green']
console.log(item); // 'red'
// case 2
var colors = new Array('black');
var count = colors.unshift('red', 'green'); // 入队方法,从数组头部推入值
console.log(colors); // ['red', 'green', 'black']
console.log(count); // 3

上面代码中的count为数组被操作后的长度。

重排序方法

var arr1 = [1, 2, 3, 4, 5];
arr1.reverse(); // 反转数组的顺序
console.log(arr1); // [5, 4, 3, 2, 1]

var arr2 = [0, 1, 5, 10, 15]
arr2.sort();
console.log(arr2); // [0, 1, 10, 15, 5]

sort()方法会根据字符串的结果改变原来的顺序,因为数值5虽然小于数值10,但是sort()方法执行时会将数组中的项转换为字符串也就是"5"和"10",这是"10"则位于"5"的前面。那么该怎么进行正确的数值排序呢?

var arr2 = [0, 1, 8, 5, 10, 15]
arr2.sort(function(a, b) { // 在数组中a是b的前一项
    return a - b; // 此时为升序,b - a 则为降序
});
console.log(arr2); // [0, 1, 5, 8, 10, 15]

注:reverse()sort()两个方法均会修改原数组。

操作方法

concat()基于当前数组的所有项创建新数组,不修改原数组,返回新数组

var colors1 = ['red', 'green', 'blue'];
var colors2 = colors1.concat('yellow', ['black', 'brown']);
console.log(colors1); // ["red", "green", "blue"]
console.log(colors2); // ["red", "green", "blue", "yellow", "black", "brown"]

slice()能够基于当前数组中的一个或多个创建一个新数组。其接受一或两个参数,即要返回项的起始和结束位置,不修改原数组,返回新数组

var colors1 = ['red', 'green', 'blue', 'yellow', 'purple'];
var colors2 = colors1.slice(1); // ['green', 'blue', 'yellow', 'purple']
var colors3 = colors1.slice(1, 4); // // ['green', 'blue', 'yellow'] 不包括结束位置项

splice()可在原数组上面进行 删除插入替换 操作。

删除: 2个参数 — 起始位置位置和要删除的项数。arr.splice(0, 2)删除数组中前两项。

插入: 至少3个参数 — 起始位置,要删除的项数,后面均参数为插入项。先删除指定项,再插入。arr.splice(2, 0, 'red', 'green')从当前数组的下标2处删除0项,然后插入字符串'red''green'

替换: 至少3个参数,先删除指定位置的项,然后插入新的项。arr.splice(2, 1, 'red', 'green')

var colors = ['red', 'green', 'blue'];
var removed = colors.splice(0, 1); // 删除第一项
console.log(colors); // ["green", "blue"]
console.log(removed); // ["red"]

removed = colors.splice(1, 0, 'yellow', 'orange'); // 从位置1开始插入两项
console.log(colors); // ["green", "yellow", "orange", "blue"]
console.log(removed); // []

removed = colors.splice(1, 1, 'red', 'purple'); // 插入两项,删除一项
console.log(colors); // ["green", "red", "purple", "orange", "blue"]
console.log(removed); // ["yellow"]

位置方法

indexOf( '查找项' )数组中若存在该项,则返回其在数组中位置的值,不错在则返回 -1

var colors = ['red', 'green', 'blue'];
console.log(colors.indexOf('blue')); // 2

迭代方法

es5为数组定义了5个迭代方法。每个方法都接收两个参数:要在每一项上运行的函数和运行该函数的作用域对象(可选)— 影响this的值。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。

1. every() - 返回布尔值

对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true

var numbers = [1, 2, 3, 4, 5];
var everyResult = numbers.every(function(item) {
    return item > 2;
});
console.log(everyResult); // false

2. some() - 返回布尔值

对数组中的每一项运行给定函数,如果该函数中有一项返回true,则返回true;

var numbers = [1, 2, 3, 4, 5];
var someResult = numbers.some(function(item) {
    return item > 2;
});
console.log(someResult); // true

3. filter() - 返回新的数组

对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组。

var numbers = [1, 2, 3, 4, 5, 0, 1];
var filterResult = numbers.filter(function(item) {
    return item > 2;
});
console.log(filterResult); // [3, 4, 5]

4. map() - 返回新的数组

对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。

var numbers = [1, 2, 3, 4, 5, 0, 1];
var mapResult = numbers.map(function(item) {
    return item * 2;
});
console.log(mapResult); // [2, 4, 6, 8, 10, 0, 2]

5. forEach() - 没有返回值

对数组中的每一项运行给定函数,且该方法没有返回值。

var numbers = [1, 2, 3, 4, 5, 0, 1];
numbers.forEach(function(item) {
    item * 2;
});
console.log(numbers); // [1, 2, 3, 4, 5, 0, 1] 原数组不会被修改

注:上面5个迭代方法均不会修改原数组。

归并方法

es5新增了两个归并数组的方法:reduce()reduceRight()。这两个方法都会迭代数组的所有项,然后构建一个最终的返回值。其中reduce()方法从数组的第一项开始,逐个遍历到最后。而reduceRight()则从数组的最后一项开始,向前遍历到第一项。

这两个方法都接收两个参数:一个在每一项上调用的函数和作为归并基础的初始值(可选)。传给reduce()reduceRight()的函数接收4个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。

下面看一下代码是具体怎么表现的吧。

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

第一次执行回调函数,prev是1,cur是2。第二次prev是3,(1加2的结果),cur是3(数组的第三项)。这个过程会持续把数组的每一项都访问一边,最后返回结果。

reduceRight()的作用类似,只不过方向相反而已。使用reduce()还是reduceRight()主要取决于要从哪头开始遍历数组。

ES6 数组的扩展

1. Array.from() 和 Array.of()

Array.from()方法用于将两类对象转换为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构SetMap)。

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
}
// ES5的写法
var arr1 = [].slice.call(arrayLike);
console.log(arr1); // ["a", "b", "c"]
// ES6的写法
let arr2 = Array.from(arrayLike);
console.log(arr2); // ["a", "b", "c"]

实际应用中,常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象。

Array.from('hello'); // ["h", "e", "l", "l", "o"]
let strSet = new Set(['a', 'b']);
Array.from(strSet); // ['a', 'b']

只要是部署了Iterator接口的数据结构,Array.from()都能将其转为数组。

Array.from()方法支持类似数组的对象。所谓类似数组的对象,本质特征只有一点,即必须由length属性。因此,任何有length属性的对象,都可以通过Array.from()方法转换为数组。

Array.of()方法用于将一组值转换为数组。

Array.of(1, 2, 3); // [1, 2, 3]
Array.of(3); // [3]
Array.of(3).length; // 1

2. 数组实例的方法

注:下面方法均在数组实例上调用

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

Array.prototype.copyWithin(target, start = 0, end = this.length)

[1, 2, 3, 4, 5].copyWithin(0, 3); // [4, 5, 3, 4, 5]

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

var result = [1, 5, 10, 15].find((value, index, arr) => {
    return value > 9
});
console.log(findReslt); // 10

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

var index = [1, 5, 10, 15].findIndex((value, index, arr) => {
    return value > 9
});
console.log(index); // 2

fill()方法使用给定值填充一个数组。

['a', 'b', 'c'].fill(7); // [7, 7, 7]
new Array(3).fill(6); // [6, 6, 6]

ES6提供了3个用于遍历数组的新方法:entries()keysvalues。它们都返回一个遍历器对象,可用for ... of循环遍历,唯一的区别在于keys()是对键名的遍历,values()是对键值的遍历,entries()是对键值对的遍历。

for(let index of ['a', 'b'].keys()) {
    console.log(index);
} 
// 0 
// 1

for(let value of ['a', 'b'].values()) {
    console.log(value);
} 
// 'a' 
// 'b'

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

Array.prototype.includes()方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的include()方法类似。

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

[NaN].indexOf(NaN); // false
[NaN].includes(NaN); // true

总结

这篇文章中汇总了JavaScript中有关数组(Array类型)操作的一些经常使用的原生方法。可供我们快速温习使用。