数组中常用的方法
1.实现数组增删改的方法
这一部分的方法都会改变原有的数组
push
push:向数组末尾增加内容
参数:多个任意类型
返回值:新增后数组的长度
let arr = [10,20];
let res = arr.push(30,'aa');
// 基于原生js操作键值对的方法,也可以实现向数组末尾增加一项新的内容
arr[arr.length] = 40;
console.log(res,arr); //=> 4, [10,20,30,'aa',40]
unshift
unshift: 向数组开始位置增加内容
参数: 多个任意类型
返回值: 新增数组长度
let ary = [10,20];
let res = ary.unshift(30,'AA');
console.log(res,ary); //=>4 [30,'AA',10,20]
// 基于原生ES6展开运算符,把原有的ARY克隆一份,再新的数组中创建第一项,其余内容使用原始ARY中的信息即可,也算实现了向开始追加的效果
ary = [100,...ary];
console.log(ary); //=>[100,30,'AA',10,20]
shift
shift: 删除数组中的第一项
参数: 无
返回值:删除的那一项
let ary = [10,20,30,40];
let res = ary.shift();
console.log(res,ary); //=> 10 [20,30,40]
// 基于原生js中的delete,把数组当作普通对象,确实可以删除掉某项一项的内容,但是不会影响数组本身的结构特点(length长度不会跟着修改),真实项目中杜绝这样使用
/*delete ary[0];
console.log(ary); //=> {1:30,2:40,length:3} */
pop
pop: 删除数组中的最后一项
参数:无
返回值: 删除的那一项
let ary = [10,20,30,40];
let res = ary.pop();
console.log(res,ary); // 40 [10,20,30]
// 基于原生js让数组的数组长度干掉一位,默认干掉的就是最后一项
ary.length--;
console.log(ary); //=> [10,20]
splice
splice:实现数组的增加,删除,修改
参数:n,m(都是数字) 从索引n开始,删除m个元素(m不写,是删除到末尾);
n,m,x 从索引n开始删除m个元素,用x占用删除的部分
n,0,x 从索引n开始,一个都不删,把x放到索引n的前面
返回值:把删除的部分用新数组存储起来返回
let ary = [10,20,30,40,50,60,70,80,90];
let res = ary.splice(2,4);
console.log(res,ary); //=> [30,40,50,60] [10,20,70,80,90]
/*
res = ary.splice(0);
// 基于这种方法可以清空一个数组,把原始数组中的内容以新数组存储起来(有点类似数组克隆;把原来数组克隆一份一模一样的数组给新数组)
console.log(res,ary); //=> [10,20,70,80,90]
*/
// 删除最后一项
ary.splice(ary.length - 1);
console.log(ary); // [20,70,80,90]
// 删除第一项
ary.splice(0,1);
console.log(ary); // [70,80,90]
let ary = [10,20,30,40,50];
let res = arr.splice(1,2,'好好学习','天天向上');
console.log(res,ary); //=> [20,30] [10,'好好学习','天天向上',40,50]
// 实现增加
ary.splice(3,0,'HelloWorld');
console.log(ary); //=> [10,'好好学习','天天向上','HelloWorld',40,50]
// 向数组末尾追加
ary.splice(ary.length,0,'AAA');
console.log(ary); //=>[10,'好好学习','天天向上','HelloWorld',40,50,'AAA']
// 向数组开始追加
arr.splice(0,0,'BBB');
console.log(ary); //=>['BBB',10,'好好学习','天天向上','HelloWorld',40,50,'AAA']
2.数组的查询和拼接
此组方法中,原数组不会改变
slice
slice: 实现数组的查询
参数:n,m 都是数字 从索引n开始,找到索引m的地方(不包含m这一项)包左不包右
返回值:把找到的内容以一个新数组的形式返回
let ary = [10,20,30,40,50];
let res = ary.slice(1,3);
consloe.log(res); //=> [20,30]
// m不写是找到末尾
res = ary.slice(1);
console.log(res); //=> [20,30,40,50]
// 数组的克隆,参数0不写也可以
res = ary.slice(0);
console.log(res); //=> [10,20,30,40,50]
思考
- 如果n/m为负数会发生啥
- n>m会发生啥
- 如果是小数会发生啥
- 如果是非有效数字会发生啥
- 如果m或者n的值比最大索引都大会发生啥
- 这种方法也叫浅克隆,深克隆是什么?
// 当只有一个参数n时,n为负数,会将负的参数加上数组的长度
let ary = [10,20,30,40,50];
let res = ary.slice(-3); //=> 相当于ary.slice(5+(-3))
console.log(res); //=> [30,40,50]
// 当有两个参数n,m时,第一个参数和第二个参数如果为负的,就都先加上数组的长度,关键在于加完后的第一个参数start应该比第二个参数end小,否则取不到东西,返回则为空。
let res1 = ary.slice(-1,3); //=> 相当于ary.slice((-1)+5,3) => ary.slice(4,3)
let res2 = ary.slice(-1,-3); //=> 相当于ary.slice((-1)+5,(-3)+5) => ary.slice(4,2)
let res3 = ary.slice(-3,-1); //=> 相当于ary.slice((-3)+5,(-1)+5) => ary.slice(2,4)
let res4 = ary.slice(-3,3); //=> 相当于ary.slice((-3)+5,3) => ary.slice(2,3)
let res5 = ary.slice(1,-3); //=> 相当于ary.slice(1,5+(-3)) => ary.slice(1,2)
console.log(res1); //=> []
console.log(res2); //=> []
console.log(res3); //=> [30,40]
console.log(res4); //=> [30]
console.log(res5); //=> [20]
// 当第一个参数n比第二个参数m大时,如果两个参数全是正数,则全返回空数组[];如果是n是正数而m为负数,则根据具体情况分析
let ary = [10,20,30,40,50];
let res1 = ary.slice(4,2);
console.log(res1); //=> []
let res2 = ary.slice(1,-3); //=> 相当于ary.slice(1,5+(-3)) => ary.slice(1,2)
console.log(res2); //=> [20]
// 如果两个参数m,n都为小数,如果参数为正数,则向下取整;如果为参数负数,则向上取整
let ary = [10,20,30,40,50];
let res1 = ary.slice(1.1,4.9); //=> ary.slice(1,4)
console.log(res1); //=> [20, 30, 40]
let res2 = ary.slice(1.1,6.4); //=> ary.slice(1,6)
console.log(res2); //=> [20, 30, 40, 50]
let res3 = ary.slice(-2.9,5); //=>ary.slice(-2,5)=>ary.slice((-2)+5,5)=>ary.slice(3,5)
console.log(res3); //=> [40,50]
// 当两个参数不是有效数字时,如果两个参数为字符串,会将字符串先通过Number()转换为数字,再执行方法;否则,返回空数组[]
let ary = [10,20,30,40,50];
let res1 = ary.slice("1","-3"); //=> ary.slice(1,-3)
console.log(res1); //=> [20]
let res2 = ary.slice("Hello","World");
console.log(res2); //=> []
// 当两个参数都比索引大时,返回结果为空数组
let ary = [10,20,30,40,50];
let res1 = ary.slice(6,7);
let res2 = ary.slice(7,6);
console.log(res1); //=> []
console.log(res2); //=> []
concat
concat : 实现数组拼接
参数:多个任意类型值
返回值: 拼接后的新数组(原数组不变)
let ary1 = [10,20,30];
let ary2 = [40,50,60];
let res = ary1.concat('day,day,up!',ary2);
console.log(res); //=> [10,20,30,'day,day,up!',40,50,60]
3.把数组转换为字符串
原有数组不变
toString
toString : 把数组转换为字符串
参数:无
返回值:转换后的字符串(原来的数组不变)
let ary = [10,20,30];
let res = ary.toString();
console.log(res); //=> "10,20,30"
console.log([].toString()); //=> ""
console.log([12].toString()); //=> "12"
join
join: 把数组转换为字符串
参数:指定的分隔符(字符串格式)
返回值:转换后的字符串(原数组不变)
let ary = [10,20,30];
let res = ary.join('');
console.log(res); //=>"102030"
res = ary.join();
console.log(res); //=>"10,20,30"
res = ary.join("|");
console.log(res); //=>"10|20|30"
res = ary.join('+');
console.log(res); //=> "10+20+30"
console.log(eval(res)); //=>60 eval把字符串变为JS表达式
4.检测数组中是否包含某一项
indexOf / lastIndexOf / includes
indexOf / lastIndexOf:检测当前项在数组中第一次或者最后一次出现位置的索引值(在IE6~8中不兼容)
参数:要检索的这一项内容
返回值:这一项出现的位置索引值(数字),如果数组中没有这一项,返回值的结果是-1, 原数组不变
let ary = [10, 20, 30, 10, 20, 30];
console.log(ary.indexOf(20)); //=>1
console.log(ary.lastIndexOf(20)); //=>4
// 想验证ary中是否包含'40'
if (ary.indexOf('40') === -1) {
//不包含
console.log("不包含");
}
// 也可以直接使用ES6新提供的includes方法判断
if (ary.includes('40')) {
// 包含:如果存在返回的是true
console.log("包含");
}
5.数组的排序或排列
reverse
reverse: 把数组倒过来排列
参数:无
返回值:排列后的新数组,原来数组改变
let ary = [12,15,9,28,10,22];
ary.reverse();
console.log(ary); //=> [22,10,28,9,15,12]
sort
sort: 实现数组的排序
参数:arr.sort([compareFunction])
compareFunction
可选 用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点 进行排序。
firstEl
第一个用于比较的元素。
secondEl
第二个用于比较的元素。
返回值:排序后的新数组,原来的数组改变
let ary1 = [7,8,5,2,4,6,9];
ary.sort();
console.log(ary1); //=>[2,4,5,6,7,8,9]
// sort方法中如果不传参数,是无法处理10以上的数字排序的(它默认按照每一项第一个字符来排)
let ary2 = [12,15,9,28,10,22];
ary.sort();
console.log(ary2); //=> [10,12,15,22,28,9]
如果没有指明
compareFunction
,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。例如 “Banana” 会被排列到 “cherry” 之前。当数字按由小到大排序时,9应该出现在 80 之前,但因为(没有指明compareFunction
),比较的数字会先被转换为字符串,所以在Unicode顺序上 “80” 要比 “9” 要靠前。
如果指明了
compareFunction
,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:
如果
compareFunction(a, b)
小于 0 ,那么 a 会被排列到 b 之前;如果
compareFunction(a, b)
等于 0 , a 和 b 的相对位置不变。如果
compareFunction(a, b)
大于 0 , b 会被排列到 a 之前。
compareFunction(a, b)
必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。
// 所以,比较函数格式如下:
function compare(a, b) {
if (a < b ) { // 按某种排序标准进行比较, a 小于 b
return -1;
}
if (a > b ) {
return 1;
}
// a must be equal to b
return 0;
}
要比较数字而非字符串,比较函数可以简单的以 a 减 b,如下的函数将会将数组升序排列
function compareNumbers(a, b) {
return a - b;
}
sort
方法可以使用 函数表达式方便地书写:
var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers);
也可以写成:
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers);
// [1, 2, 3, 4, 5]
6.遍历数组的每一项的方法
forEach
forEach:遍历数组中的每一项内容
参数: 回调函数
返回值:无 原数组不变
let ary = [12,15,9,28,10,22];
// 基于原生js中的循环可以实现
for (let i = 0;i < ary.length;i++) {
// i:当前循环这一项的索引
// ary[i]:根据索引获取循环的这一项
console.log('索引'+i+'内容'+ary[i]);
}
// forEach()实现
ary.forEach((item,index) => {
// 数组中有多少项,函数就会被默认执行多少次
// 每一次执行函数:item是数组中当前要操作的这一项,index是当前项的索引
console.log('索引'+index+'内容'+item);
});
map
filter
find
reduce
some
every
…
7.数组去重的方法
方案一
let ary = [1,2,3,1,2,3,1,2,3];
/*循环原有的数组中的每一项,添加到空数组中,每次添加的时候验证一下,新数组中是否已经存在这一项,不存在再增加 */
let newAry = [];
for (let i = 0; i < ary.length; i++) {
// 循环获取原数组中的每一项
let item = ary[i];
// 验证新数组中是否存在这一项
if (newAry.includes(item)) {
// 存在这一项,不在增加到新数组中,继续下一轮循环即可
continue;
}
// 新数组中不存在这一项,我们加入到新数组中即可
newAry.push(item);
}
console.log(newAry);
// 上述代码的优化
let ary = [1,2,3,1,2,3,1,2,3];
let newAry = [];
ary.forEach(item => {
if(newAry.includes(item)) return;
newAry.push(item);
});
console.log(newAry);
方案二
// 循环原来数组的每一项,每一次拿出来的值都跟它后边的值进行比较
// 比较的过程中遇到与自己相同的,把这一项从数组中删除=> splice
let ary = [1, 2, 3, 1, 2, 3, 1, 2, 3];
for (let i = 0; i < ary.length; i++) {
// item: 每次拿出来的当前项
// i:当前项的索引 i+1:代表后一项
let item = ary[i];
// 让当前项和后面的每一项进行比较(循环)
for (let j = i + 1; j < ary.length; j++) {
// compare:后面拿出来要比较的一项
let compare = ary[j];
// 如果compare和item相等,说明这一项是重复的,我们把它删掉
if (compare === item) {
// j索引这一项要从数组中移除
ary.splice(j, 1);
/* 数组会发生塌陷:j后面的每一项索引都会提前一位,下次要比较的应该还是j这个索引的内容 */
j--; // 所以每次将j--,防止循环后j++
}
}
}
console.log(ary);
方案三
// 基于对象的方法,优化
let ary = [1,2,3,1,2,3,1,2,3];
// 1.创建一个空对象
let obj = {};
// 2.循环数组中的每一项,把每一项向对象中进行存储 => item:item
for (let i = 0;i < ary.length;i++) {
let item = ary[i];
// 3.每一次存储之前进行判断;验证obj中是否存在这一项
if (obj[item] !== undefined) {
// 已存在这一项
ary.splice(i,1);
i--;
continue;
}
obj[item] = item;
}
console.log(obj);
方案四
// 对方案三的优化
// 基于splice实现删除性能不好;当前项被删除后,后一项的索引都要向前提一位,如果后面内容过多,一定影响性能
let ary = [1,2,3,1,2,3,1,2,3];
let obj = {};
for (let i = 0;i < ary.length;i++) {
let item = ary[i];
if (obj[item] !== undefined) {
ary[i] = ary[ary.length-1]; // 将最后一项的值给当前项
ary.length--; // 数组长度减一,即可将数组最后一位删掉
i--; // 由于原来的最后一项的值为当前项,因此还要与此项对比,为防止i++,进行i--
continue;
}
obj[item] = item;
}
console.log(obj);
对此方案,创建数组去重的函数
unique:实现数组去重的方法
参数:要去重的数组
返回值:去重后的数组
function unique(ary) {
let obj = {};
for (let i = 0;i < ary.length;i++) {
let item = ary[i];
if (obj[item] !== undefined) {
ary[i] = ary[ary.length-1];
ary.length--;
i--;
continue;
}
obj[item] = item;
}
return ary;
}
方案五
// 基于ES6的Set实现去重
let ary = [1,2,3,1,3,2,1,2,3];
ary = [...new Set(ary)];
console.log(ary);