JavaScript浅析 -- 数组方法(上)

一、数组的增删改查

增加数组元素的方法有push / unshift,删除数组元素的方法有pop / shift,还有万能的增删改都可以的splice,以及查找数组元素的indexOf / lastIndexOf,下面我们一一讲解下区别。

1. push方法

从数组的最后插入(push压入)新元素,返回的结果是数组的长度。

var arr = [0, 1, 2, 3];
arr.push(4); // arr变成[0, 1, 2, 3, 4],此句执行的结果是arr.length即5
arr.push(5, 6); // arr变成[0, 1, 2, 3, 4, 5, 6],此句执行的结果是arr.length即7
2. pop方法

与push相对应的,pop是将数组的最后一个元素删除(pop弹出),返回的结果是被删除的该元素。

var arr = [1, 2, 3, 4];
arr.pop(); // arr变成[1, 2, 3],此句执行的结果是被删除的元素4
3. unshift方法

unshift也是插入新元素,不过是从数组的最开始插入,返回的结果也是插入后数组的长度。

var arr = [0, 1, 2, 3];
arr.unshift(4); // arr变成[4, 0, 1, 2, 3],此句执行的结果是arr.length即5
arr.unshift(5, 6); // arr变成[5, 6, 4, 0, 1, 2, 3],此句执行的结果是arr.length即7
4. shift方法

与unshift对应的,shift是删除最开始即第一个元素,返回的结果是被删除的该元素。

var arr = [1, 2, 3, 4];
arr.shift(); // arr变成[2, 3, 4],此句执行的结果是被删除的元素1
5. splice方法

splice方法就比较强大了,可以增加删除和查看元素,而且还可以指定位置。使用方法splice(index, num, value1, value2, ..., valuen),第一个参数是操作的位置,第二个参数是改变的元素个数,第三个是插入或替换的值,后面也都是要插入和替换的值。返回的结果是被改变元素构成的数组。

var arr = [1, 2, 3, 4];
// 增加元素,由于增加元素不会改变原数组元素的值,所以第二个参数为0
arr.splice(1, 0, 5);  // 在数组下标为1即数组里元素2的位置,插入一个元素5,数组变为[1, 5, 2, 3, 4],此句返回结果是[](因为原数组没有被删除或替换的元素)。
arr.splice(0, 0, 6, 7); // 数组变为[6, 7, 1, 5, 2, 3, 4],返回的也是[]

// 删除元素,由于删除不需要新插入和替换的值,所以只需传前两个参数
arr.splice(0, 3); // 从index为0的位置开始,从左往右删除3个元素,数组变为[5, 2, 3, 4],此句返回的结果是[6, 7, 1]
arr.splice(3, 8); // 从index为3的位置开始,数组变为[5, 2, 3],此句返回[4]

// 替换元素,替换元素由于原数组的元素有变化,所以不为0,注意替换的个数和后面传的元素个数不一致可以做到替换的同时增删
arr.splice(0, 3, 1, 2, 3); // 从第一个元素开始,从左往右替换3个元素,数组变为[1, 2, 3],输出结果为被替换元素数组[5, 2, 3]
arr.splice(0, 2, 3, 2, 1, 2);  // 替换的同时添加,此时arr为[3, 2, 1, 2, 3],返回结果[5, 2]
arr.splice(2, 3, 1, 0); // 替换的同时删除,此时arr为[3, 2, 1, 0],返回结果为[1, 2, 3] 

或许有小伙伴已经被绕晕了,其实没必要记住那么多规律,知道每个参数代表啥再去推算就好,多看看例子就明白了。

6. indexOf和lastIndexOf方法

第一个参数指定查找元素,第二个参数指定从哪个位置开始找(没设默认0开始找),返回第一次被找到的下标值,若没有返回-1。而lastIndexOf基本类似,只是从最后一个元素开始倒着找。若第二个参数超出数组的长度范围,则直接返回-1。

var arr = ['str', 1, 2, 'str', 6];
arr.indexOf('str'); // 0
arr.indexOf('str', 1); // 4,从第二位开始往后找
arr.lastIndexOf('str'); // 4
arr.lastIndexOf('str', 1); // 0,从倒数第二位开始往前找
arr.indexOf('haha'); // -1
arr.indexOf('str', -1); // -1
arr.indexOf('str', 5); // -1

注意,其内部用的是严格等于(===)去比较是否相等,所以无法查找NaN,因为NaN===NaN返回false。

var arr = ['1', 1, 2, NaN];
arr.indexOf(1); // 1
arr.indexOf('1'); // 0
arr.indexOf(NaN); // -1
arr.lastIndexOf(NaN); // -1

二、数组的排序

1. sort方法

sort用于数组排序,会改变原数组,返回值是排好序的数组。有两种调用方式:

  • 直接调用,则按默认排序。即按数字大小或字符串的unicode编码大小进行排序,对象会调用toString()再按编码排序,若有undefined则放在最后。
  • 传自定义函数作为参数调用,当这个函数返回负值时表示第一个数应该位于第二个数前面,当返回0则相等,当返回正值时表示第一个数应该位于第二个数后面。
var arr1 = [1, 5, 2, 8, 6];
arr1.sort(); // [1, 2, 5, 6, 8]
var arr2 = ['1', '8', '7', '10'];
arr2.sort();  // ["1", "10", "7", "8"],字符串先比较的第一位的unicode编码值
// 为了得到正确的排序数组可以自定义函数
arr2.sort(function(a, b) {
  return a - b; // 由于减法运算会先转数字再运算,所以可以正确排序
}); // ["1", "7", "8", "10"]

一般数字的对比,直接用减法就满足需求;如果是字符串要比较unicode值大小的,可以用><进行判断。看下面两个比较常见的例子:

// 要求按姓名进行排序
var users = [
  {name: 'Peter', born: '2018-7-12'}, 
  {name: 'Bake', born: '2018-3-15'}, 
  {name: 'John', born: '2016-4-18'}
];
users.sort(function(a, b) {
  if(a.name > b.name) {return 1;}
  else if(a.name < b.name) {return -1;}
  else {return 0;}
}); 
// [{name:"Bake", born:"2018-3-15"}, {name:"John", born:"2016-4-18"}, {name:"Peter", born:"2018-7-12"}]

// 要求按出生日期先后进行排序
users.sort(function(a, b) {
  return new Date(a.born) - new Date(b.born);
});
// [{name:"John", born:"2016-4-18"}, {name:"Bake", born:"2018-3-15"}, {name:"Peter", born:"2018-7-12"}]
2. reverse方法

将数组进行逆序,会改变原数组,返回值会逆序数组。注意是逆序(反转下前后顺序),而不是倒序(按顺序递减排好)。

var arr = [1, 5, 3, 8, 6];
arr.reverse(); // [6, 8, 3, 5, 1]

三、数组的拼接

1. join方法

用指定参数作为分隔符连接数组元素,返回连接后的字符串。若没参数默认是','连接,若是有空位或undefined或null则转成空字符连接。

var arr = [1, 5, , 8, undefined, 6, null, 7];
arr.join('-'); // "1-5--8--6--7"
arr.join(); // "1,5,,8,,6,,7"
2. concat方法

concat用于数组或数组元素的合并,返回一个合并后的新数组,注意原数组不发生改变。

var arr1 = [1, 2], arr2 = [3, 4];
arr1.concat(arr2); // [1, 2, 3, 4]
arr1.concat({a: 1, b: 2}, {c: 3}); // [1, 2, {a:1, b:2}, {c:3}]
arr1.concat(3, 4, 5); // [1, 2, 3, 4, 5]

注意,若合并的元素是对象,则concat合并后的元素是引用,所以可以用来浅拷贝对象。

var arr = [1, 2, {a: 3, b: 4}];
var newArr = [].concat(arr); // 或者arr.concat(),都返回[1, 2, {a:3, b:4}]
newArr[2].a = 666;
console.log(arr); // [1, 2, {a:666, b:4}],由于是引用,所以原来arr的a也会被改变

四、数组元素处理

1. reduce方法

reduce方法接受两个参数,第一个参数是一个函数,第二个参数是默认初始值。而第一个函数也有两个参数,第一个参数是数组第一个元素或初始值或上一个函数返回的结果,第二个参数是数组的下个元素。来看个例子:

var arr = [1, 2, 3];
arr.reduce(function(a, b) {
    return a + b;
});
// 第一次:没有初始值,a是数组第一个元素1,b是下个元素2
// 第二次:a是上次函数的结果3,b是下个元素3
// 没有下个数组元素,遍历结束,结果返回6

arr.reduce(function(a, b) {
    return a + b;
}, 4);
// 第一次:有初始值,a是初始值4,b此时是第一个元素1
// 第二次:a是上次函数的结果5,b是下个元素2
// 第三次:a是上次函数的结果7,b是下个元素3
// 没有下个数组元素,遍历结束,结果返回10

一般尽量指定一个默认初始值,因为没有初始值对空数组reduce处理会报错。

[].reduce(function(a, b) {
    return a + b;
}); // Uncaught TypeError: Reduce of empty array with no initial value

[].reduce(function(a, b) {
    return a + b;
}, 0); // 0

reduce主要用处是存储上个元素遍历的处理结果,用于下个元素处理,来看看两个例子:
(1)找最大长度字符串

['hello js', 'hello', 'js'].reduce(function(longest, value) {
    return value.length > longest.length ? value : longest;
}, '');
// "hello js"

(2)数组元素去重

// 合并两个数组,当cardUrl一样时保留arr1的元素
var arr1 = [
    {url:'/a',cardUrl:'rUbAF3EFJjyyfYRrU3zIj2Ez'},
    {url:'/b',cardUrl:'JnAfYbvqaQfy6bqyeiEjIZjm'},
    {url:'/c',cardUrl:'7r2MFfzyQVryeEVVf2QfU7nq'},
],
arr2 = [
    {url:"/d",cardUrl:"nua67bfa6n2qr2eUJbimeaQj"},
    {url:'/e',cardUrl:"rUbAF3EFJjyyfYRrU3zIj2Ez"},
];
let arr = [...arr1,...arr2]; // 拼接数组,相当于concat
let hash = {};
arr = arr.reduce(function(item, next) { // 如果已存在则丢弃,否则放入结果集
    hash[next.cardUrl] ? '' : hash[next.cardUrl] = true && item.push(next);
    return item;
}, []);
/* [
  {url: "/a", cardUrl: "rUbAF3EFJjyyfYRrU3zIj2Ez"},
  {url: "/b", cardUrl: "JnAfYbvqaQfy6bqyeiEjIZjm"},
  {url: "/c", cardUrl: "7r2MFfzyQVryeEVVf2QfU7nq"},
  {url: "/d", cardUrl: "nua67bfa6n2qr2eUJbimeaQj"} 
] */
2. reduceRight方法

此法与reduce用法基本一致,只是遍历的时候是倒序遍历。

var arr = [1, 2, 3];
arr.reduceRight(function(a, b) {
    return a + b;
}, 4);
// 第一次:有初始值,a是初始值4,b此时是倒数第一个元素3
// 第二次:a是上次函数的结果7,b是倒数第二个元素2
// 第三次:a是上次函数的结果9,b是倒数第三个元素1
// 没有倒数第四个数组元素,遍历结束,结果返回10

推荐阅读更多精彩内容

  • 数组总共有22种方法,本文将其分为对象继承方法、数组转换方法、栈和队列方法、数组排序方法、数组拼接方法、创建子数组...
    Sachie阅读 554评论 0 6
  • join() Array.join()方法将数组中所有元素都转化为字符串并连接在一起,返回最后生成的字符串。可以指...
    lidroid本人阅读 210评论 0 3
  • 由于最近都在freecodecamp上刷代码,运用了很多JavaScript数组的方法,因此做了一份关于JavaS...
    来自星星的尼玛阅读 1,096评论 0 16
  • 雨夜无眠 愁丝万千 残窗幽径睡莲 回眸一眼 遗恨荒年 筱竹淡月 华发新城 青丝转雪 幽幽念 苦苦忆 此情可待成追忆...
    山海未可知阅读 72评论 0 2
  • 今天第一节课上的是数学。我们学到了25页,第二节课也是数学,我们做口算题卡,我的给数学老师了,数学老师找不到我的口...
    付梦缘阅读 186评论 1 0