数组在前端中非常重要!不仅笔试题面试中出现频率高,而且在平时前端开发中也经常用到!将数组方法分为两类:
一、改变原数组的方法
- 作用于数组末端的方法:
- arr.push(“Apple”):在数组末端添加一个或多个元素,返回数组长度
- arr.pop():取出并返回数组最后一个元素,若该数组为空,则返回undefined
- 作用于数组首端的方法:
- arr.unshift(“Apple”) :在数组首端添加一个或多个元素,返回数组长度
- arr.shift():取出并返回数组的第一个元素 ,若该数组为空,则返回undefined
// 定义一个数组
var arr=[1,2,3,4,5]
// 作用于数组末端的方法
var a=arr.push(6) //a=6 arr=[1,2,3,4,5,6]
var del1=arr.pop() //del1=6 arr=[1,2,3,4,5]
// 作用于数组首端的方法
var b=arr.unshift(0) //b=6 arr=[0,1,2,3,4,5]
var del2=arr.shift() //del1=0 arr=[1,2,3,4,5]
- arr.reverse() :将数组原位逆序
- arr.splice(start[, deleteCount, elem1, …, elemN]):添加,删除元素
从索引 start 开始修改arr:删除 deleteCount 个元素并在当前位置插入elem1, …,
elemN。并返回被删除元素组成的数组
let arr=["1","study","JavaScript","right","now"]
// 删除数组的前三项,并使用其他内容代替
arr.splice(0,3,"let's","dance")
alert(arr) // 现在 ["let's","dance","right","now"]
- arr.sort():对数组进行原位排序且返回。不写函数的话会按照字符串UniCode码排序
sort里写函数时,函数里必须写两个形参,根据返回值决定排序:
当返回值为负数,那么前面的数放在前面;为正数,那么后面的数在前;为0,不动
如:arr=[1,3,5,4,10] 比较顺序是1和3,1和5,1和4,1和10,3和5,3和4…
var arr=[20,2,10,13,4,8,9];
arr.sort(function(a,b){
return a-b//升序
return b-a//降序
})
二、不改变原数组的方法:
- arr.concat(arg1, arg2…) :创建一个包含arr,arg1,arg2元素的新数组
- arr.slice([start], [end]):从索引 start 到 end(不包括 end)的数组项复制到一个新的数组并返回
const list=['grinning','tired_face','grinning','tired_face'];
list.slice(1,3); // ['tired_face', 'grinning']
list; // ['grinning','tired_face','grinning','tired_face']
// Code
const list = [1, 2, 3, 4, 5];
list.slice(1, 3); // [2, 3]
list; // [1, 2, 3, 4, 5]
- 在数组中搜索:
- arr.indexOf(item, from):从索引 from 开始搜索 item,若找到则返回索引,否则返回-1
arr.lastIndexOf(item, from) 和arr.indexOf()相同,区别在于从尾部向首部查询
- arr.includes(item, from):从索引 from 开始搜索 item,若找到则返回 true,否则返回false
- arr.find(function):通过func过滤元素,返回使func返回true的第一个值
let result=arr.find(function(item,index,array){
// 如果返回true,则返回item 并停止迭代
// 对于假值(false)的情况,则返回undefined
});
// 代码示例:
let users=[
{id:1,name:"John"},
{id:2,name:"pete"},
{id:3,name:"Mary"}]
let user=users.find(item=>item.id==1)
alert(user.name) // John
arr.findIndex(function):返回使func返回true的第一个元素的位置
- arr.filter(function):返回所有匹配元素组成的数组(与find 相似)
let results=arr.filter(function(item,index,array){
// 如果true,item被push到results,迭代继续
// 如果什么都没找到,则返回空数组
}
- 转换数组
- arr.map(function):对数组的每个元素都调用函数,并返回结果数组【注意该方法和forEach的区别】
let result=arr.map(function(item,index,array){
// 返回新值而不是当前元素
}
//代码示例:
const list=['tired_face','tired_face','tired_face','tired_face'];
list.map(('white_circle') => 'grinning'); // ['grinning', 'grinning', 'grinning','grinning']
const list=[1,2,3,4];
list.map((el)=>el*2); // [2,4,6,8]
- arr.split():将字符串转换为数组
let names='Bilbo,Gandalf,Nazgul';
let arr=names.split(',');
for(let name of arr){
alert(`A message to ${name}.`); // A message to Bilbo
}
// 注:空参数,将字符串拆分为字母数组
let str=test;
alert(str.split('')); // [t,e,s,t]
- arr.join(glue) :创建由glue粘合的arr项,默认连接字符为 “,” 逗号【与split方法互逆】
let arr=['Bilbo','Gandalf','Nazgul'];
let str=arr.join(';'); // 使用分号将数组粘合成字符串
alert(str); // Bilbo;Gandalf;Nazgul
- arr.toString():将数组转换为字符串,以逗号分隔
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var x = fruits.toString(); // Banana,Orange,Apple,Mango
- 遍历数组:
- for循环:
let arr=['apple','banana','orange'];
for(let i=0; i<arr.length;i++) {
console.log(i,arr[i]);
}
// 0 apple
// 1 banana
// 2 orange
- for…in…循环:【主要遍历对象,不建议遍历数组】
let arr=['apple','banana','orange'];
for(let key in arr) { //key中是索引
console.log(key,arr[key]);
}
// 0 apple
// 1 banana
// 2 orange
1.遍历数组:输出的 key 是数组索引
2.遍历对象:key为对象的属性名,arr[key]为属性值
- for…of…循环:【注意:不能遍历对象!】
let arr=['apple','banana','orange'];
for(let key of arr) { // key中是值
console.log(key);
}
// apple
// banana
// orange
for…of…循环可以避免开拓内存空间,增加代码运行效率,一般用for…of…遍历数组
注意:for…of获取的是数组里的值,for…in获取的是index索引值
- arr.forEach(function):用于调用数组的每个元素,并将元素传递给回调函数。(注意该方法和map的区别,若直接打印arr.forEach,结果为undefined)
const arr=['小红','倪大红','苏大强','宝宝']
// forEach循环一旦开始,无法在中间被停止
arr.forEach((item,index)=>{
console.log('object')
if(item==='苏大强'){
console.log(index)
}
})
- arr.some(function):测试数组中是不是至少有1个元素通过了被提供的函数测试。返回的是一个Boolean类型的值
const arr=['小红','倪大红','苏大强','宝宝']
arr.some((item,index)=>{
if(item==='苏大强'){
console.log(index)
// 再找到对应项之后,可以通过return true终止some循环
return true
}
})
注意:与forEach的区别——>forEach一旦开始,无法在中间被停止;从数组中找元素,用some更合适
- arr.every(function):对数组中的每一项进行判断,若都符合则返回true,否则返回false
const arr=[
{id:1,name:'西瓜',state:true},
{id:2,name:'榴莲',state:false},
{id:3,name:'草莓',state:true}]
//需求:判断数组中,水果是否被全选了
const result=arr.every(item=>item.state)
console.log(result)
- arr.reduce(function):循环数组中的每一项进行累加,循环完之后,会把最后的累加结果return出去【每一次都会将先前元素的计算结果作为参数传入】
let value=arr.reduce(function(accumulator,item,index,array){
// ...
},[inital]);
// 代码示例:
const arr=[
{id:1,name:'西瓜',state:true,price:10,count:1},
{id:2,name:'榴莲',state:false,price:80,count:2},
{id:3,name:'草莓',state:true,price:20,count:3}]
//需求:把购物车数组中,已勾选的水果,总价累加起来
//之前的做法:
let amt=0 // 总价
arr.filter(item=>item.state).forEach(item=>{
amt+=item.price*item.count
})
console.log(amt)
//现在的做法:使用reduce
const result=arr.filter(item=>item.state).reduce((amt,item)=>{
return amt+=item.price*item.count
},0)
console.log(result)
注意:
1.无初始值,将第一个元素作为初始值,从第二个迭代
arr.reduceRight(function):从数组的最后一项开始,向前遍历到第一项
- 判断一个变量是否为数组:
- arr.isArray(value):若value为数组,返回true;否则false
// Code
arr.isArray([1, 2, 3, 4, 5]); // true
arr.isArray(5); // false
- instanceof运算符:用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上
> arr instanceof Array; // true
> // 实质:
> arr.__proto__ === Array.prototype; // true
- Object.prototype.toString.call():所有原始数据类型都能通过该方法判断,具有通用性
Object.prototype.toString.call(arr); // "[object Array]"
Object.prototype.toString.call(2); // "[object Number]"
Object.prototype.toString.call(""); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
三、最后补充
注意:面试官不仅会问:改变原数组的方法与不改变原数组的方法,还会问到哪些方法是ES5新增,哪些方法是ES6新增
- ES5新增:indexOf与lastIndexOf、forEach、map、filter、every、some、reduce与reduceRight
- ES6新增:find与findIndex、includes、isArray、for…of、扩展运算符
1.for…of与for…in与forEach的区别
2.map与forEach的区别
3.reduce用在何种情景
4.数组去重