前言
因为自己有时会记混一些JS数组操作的方法,这篇博客就对JS数组知识进行总结,常看常新。
slice 与 splice
slice:截取数组/字符串
数组/字符串.slice(start,end) [start, end) 从start下标开始,到 end-1下标结束
const arr = ['a', 'b', 'c', 'd', 'e', 'f'];
arr.slice(); // 无参数时,截取所有的元素。
arr.slice(2); // 从第二个值开始提取,直到末尾
arr.slice(-2); // 提取最后两个元素 负数会将其与长度相加,-2+6=4
arr.slice(2, 4); // 提取第二、三元素
将伪数组[]转化成数组
array = [].slice.call(arr);
ES6版:
array = Array.from(arr);
splice:对数组进行增删改查
数组.splice(start,length,新添加的元素1,元素2,...)
从第start位开始(初始为0),length个数据替换为新添加的,该方法返回被替换之前的length个数据,原数组也会被改变成替换之后的数据。可以理解成:删除了哪些元素,就在所在位置补充新的内容。
- 只传前一/二个参数,删除元素
let arr = ['a', 'b', 'c', 'd', 'e', 'f'];
arr.splice(1); //从第index为1的位置开始,删除元素
arr.splice(-2); //删除最后两个元素,和slice同样的思想
arr.splice(1, 3); //从第index为1的位置开始,一共删除三个元素
- length=0时,增加元素
let arr = ['a', 'b', 'c', 'e'];
let arr1=arr.splice(3,0,'d')
console.log(arr1) //[]
console.log(arr) //['a', 'b', 'c', 'd', 'e'];
- 增加+删除:变更数据
let arr = ['a', 'b', 'c', 'd'];
arr.splice(1,2,1,2,3,4,5)
console.log(arr1) //['b','c']
console.log(arr) //['a', 1, 2, 3, 4, 5, 'd']
- 综合例子
let arr = [];
arr[0]=1;
arr[1]=2;
arr[3]='abc';
arr[5]=true;
console.log(arr); // [1, 2, empty, "abc", empty, true]
let arr1=arr.slice(0,4)
console.log(arr1); //[1, 2, empty, "abc"]
console.log(arr); //[1, 2, empty, "abc", empty, true] 没有改变原数组
let arr2=arr.splice(0,3,3,4,5) //从下标为0开始,将这3个替换为3,4,5
console.log(arr2); //[1, 2, empty] 选中的这三个
console.log(arr) //[3, 4, 5, "abc", empty, true] 替换完的数组
区别
- 功能:slice是截取数组/字符串的,splice是对数组进行增删改查的
- 二者都会返回新的数组,但slice方法不会改变原数组,splice方法改变原数组
数组与字符串的转换——split 与 join
split:将 字符串 拆分成 数组
新的数组 = str.split(分隔符); 返回一个数组,不改变原字符串。
let str="a b c"
let arr1=str.split(" ") //["a","b","c"]
join:将 数组 转换为 字符串
新的字符串 = 原数组.join(参数); 默认使用,作为连接符,返回一个字符串,不会改变原数组
let arr = ['a', 'b', 'c'];
let str1=arr.join(); //"a,b,c" 此时和toString()的效果是一致的
let str2=arr.join('-'); //"a-b-c"
map 与 foreach
map 和 forEach 是数组中的帮助器方法,可以轻松地在数组上循环。我们曾经像下面这样循环遍历一个数组,没有任何辅助函数。
遍历:for + let
如果要循环遍历一个数组,我们很容易想到使用 for+let
let arr = [1,2,3];
for (let i = 0; i < arr.length; i += 1) {
console.log(arr[i]);
}
map
map 的作用与 for 循环完全相同,只是 map 会创建一个新数组,其结果是在调用数组中的每个元素上调用提供的函数。
数组.map(fn) 回调函数fn接受3个参数:数组的当前值str;当前值在数组中的位置i;原始数组origin
let arr = [1,2,3];
let fn = (str, i, origin) => {
console.log(`${i}: ${str} / ${origin}`);
};
arr.map(fn);
// 0: 1 / 1,2,3
// 1: 2 / 1,2,3
// 2: 3 / 1,2,3
也可以在回调里只传一个参数:
arr.map((str) => { console.log(str); })
//1
//2
//3
以下遍历后,map 后新生成的数组不等于原始数组:
let arr1=arr.map(i =>i)
arr1 //[1,2,3]
arr //[1,2,3]
forEach
数组.forEach(fn),下例中的forEach与map用法相同,都是接受一个回调函数fn作为参数:
let arr = [1,2,3];
let fn = (str, i, origin) => {
console.log(`${i}: ${str} / ${origin}`);
};
arr.forEach(fn);
// 0: 1 / 1,2,3
// 1: 2 / 1,2,3
// 2: 3 / 1,2,3
区别
主要就在于是否有返回值:map 返回基于原始数组的一个新数组,但是 forEach 的返回值是undefined。它们都能确保了原来数组的不变。
[1,2,3].map(d => d + 1); // [2, 3, 4];
[1,2,3].forEach(d => d + 1); // undefined;
综上所述,建议在创建一个新的数组时使用map;当你不需要制作一个新的数组,而是要对数据做一些事情时,就使用forEach。
数组 与 类数组
类数组
let list = {
0 : 1,
1 : 2,
2 : 3,
length : 3
}
//list.push() 报错
区别
- 类数组不具备数组的方法(如splice,split,push...)
- 类数组是一个普通对象,数组类型是Array
类数组 转化成 数组
类数组不能使用数组的方法,因此我们需要将类数组转化成真正的数组
- ES6中的 Array.from()
let arr = Array.from(list); - ES6+ 扩展运算符
let arr = [...HTMLcontrion] - 使用apply
let arr = [].concat.apply([],list)
注意
1 字符串赋值问题
有一个字符串s="abcabcbb",虽然可以遍历取到s[i],但是不能对其直接赋值,必须将字符串.split('')转换成数组,数组里的每一项都是字符,再将数组join拼接成字符串。
2 数组排序sort()问题
原理:当数组长度小于等于10的时候,采用插入排序,大于10的时候,采用快速排序。
- 无参数情况:默认会以字典排序的顺序为结果,如果处理字符串类型的数组直接使用sort就可以,数值型可能会返回错误。
let arr = [10, 5, 40, 25, 100, 1];
arr.sort();
//[1, 10 ,100, 25, 40, 5]
- 传入比较函数的情况: 具体的返回结果与比较函数有关。
对函数进行传参,可以让数组内的值按照升序/降序排序:
let arr= [40,100,1,5,25,10];
arr.sort((a,b)=>{return a-b}); //数字升序
//1,5,10,25,40,100
let fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort(); //字母降序
fruits.reverse();
//Orange,Mango,Banana,Apple
还在不断更新中