你真的了解JavaScript中的数组操作吗?

你真的了解JavaScript中的数组操作吗?

其实这篇文章拖延了很久很久,说实话工作也没那么忙,但是总觉得冥冥之中总有一种不可抗力总是拖延着你,不让你去写博客,曾经千万次的告诉自己:我一定要坚持每周至少写一篇!但是事与愿违,我知道,这一切都是借口…算了,回归正题!
大家看到这个标题,可能会很自信的说,JavaScript数组操作这么简单…真的那么简单吗?对于很多资深前端开发人员,本文似乎有些小儿科!当然,还请各位大佬多多指教!

为什么要特别写一篇关于数组操作的文章,因为数组是在我们实际项目最常用的一种变量类型,我们常常要处理很多后台返回的数据,数组操作不当或者没有特别“优雅”的处理数组数据,那会使你的项目变得晦涩难懂,冗余复杂,这一点我相信大家都有深深的体会

好啦,废话不多说!接下来我会详细的介绍数组操作方法:

(一)常规操作

常规操作就是最基础的数组的定义及方法

1.定义数组

数组的定义有很多种方式:


let arr = [] //(最常用)

let arr = new Array() // 使用 Array 构造函数创建

// 当然我们也可以这么创建
let arr = new Array(5) // 创建一个长度为 5 的数组
console.log(arr) // [empty x 5]

// 定义数组的方式当然还有很多种方式,但基本上就这两种方式:一种是使用字面量方式,一种是使用Array构造函数的方式创建!

2.push()方法

说明:向数组的末尾添加一个或者多个元素,改变原数组,并返回新数组的长度。


let names = ['zhangsan', 'lisi']
let namesLen = names.push('wangwu')

console.log(names) // ['zhangsan', 'lisi', 'wangwu']
console.log(namesLen) // 3

// 当然也可以传多个数组
names.push('zhaoliu', 'houqi')

console.log(names) // ['zhangsan', 'lisi', 'wangwu', 'zhaoliu', 'houqi']

3.unshift()方法

说明:向多个数组的开头添加一个或多个数组,改变原数组,并返回新数组的长度


let names = ['zhangsan', 'lisi']
let namesLen = names.unshift('wangwu')

console.log(names) // ['wangwu', 'zhangsan', 'lisi' ]
console.log(namesLen) // 3

// 当然也可以传多个数组
names.push('zhaoliu', 'houqi')

console.log(names) // ['zhaoliu', 'houqi', 'wangwu', 'zhangsan', 'lisi']

4.pop()方法

说明:删除数组的最后一个元素,改变原数组,并返回该元素的值


let names = ['zhangsan', 'lisi', 'wangwu']
let unitNames = names.pop()

console.log(names) // ['zhangsan', 'lisi']
console.log(unitNames) // wangwu

5.shift()方法

说明:删除数组的第一个元素,改变原数组,并返回该数组的值


let names = ['zhangsan', 'lisi', 'wangwu']
let unitNames = names.shift()

console.log(names) // ['lisi', 'wangwu']
console.log(unitNames) // zhangsan

6.solice()方法

此方法是数组基本操作中非常强大的,它有删除、插入和替换的功能,接下来一一介绍它。

  • 删除

可以删除任意的项;
接收两个参数,第一个参数为起始项,第二个参数是要删除的数量,并返回已删除的项(数组类型) 例如:

let names = ['zhangsan', 'lisi', 'wangwu']
let deleteArr = names.splice(0, 1)

console.log(names) // ['lisi', 'wangwu']
console.log(deleteArr) // ['zhangsan']

  • 插入

可以向指定位置插入任意数量的项。
接收n个参数,第一个参数为起始项,第二个为0,后面的参数就是为要插入的数据,例如:


let names = ['zhangsan', 'lisi', 'wangwu']
names.splice(2, 0, 'lisi1', 'lisi2', 'lisi3')

console.log(names) // ['zhangsan', 'lisi', 'lisi1', 'lisi2', 'lisi3', 'wangwu']

  • 替换

可以向指定位置插入任意数量的项,并且同时删除任意数量的项。
接收n个参数,第一个参数为起始项,第二个参数为要替换的数量,后面的参数就是所替换的数据,例如:


let names = ['zhangsan', 'lisi', 'wangwu']
names.splice(1, 2, 'lisi1', 'lisi2', 'lisi3')

console.log(names) // ['zhangsan', 'lisi1', 'lisi2', 'lisi3']

7.join()方法

说明:把数组变成一个字符串,分隔符为传入的字符


let names = ['zhangsan', 'lisi', 'wangwu']
let arrToStr = names.join(',')

console.log(arrToStr) // 'zhangsan,lisi,wangwu'

9.sort()方法

说明:对数组进行排序

sort()方法在使用时,它会调用每个数组项的 toString() 方法,然后比较得到的字符串,以确定如何排序。即使每一项都是数字,sort()比较的也是数值。


let values = [1, 2, 5, 10, 15]
values.sort()

console.log(values) // [1, 10, 15, 2, 5]

可以看到,sort()方法并没有按照从大到小的顺序去排列,它先是把数字转换成字符串再去比较的。‘10’,和 ‘5’ 比较, 自然 ’5‘大。然而sort()在实际项目中往往用的是另一种方法:


let values = [1, 2, 5, 15, 10]

const compare = function(val1, val2) {

  if(val1 < val2) {
    return -1
  } else if(val1 > val2) {
    return 1
  } else {
    return 0
  }
}
values.sort(compare)

console.log(values) // [1, 2, 5, 10, 15]

当然也可以将 compare() 函数简化一下:


const compare = function(val1, val2) {

  return val2 - val1 // 从小到大的顺序

  // return val1 - val2 // 从大小的顺序

}

10.slice()方法

说明: 分割数组,可以接收一个或者两个参数;一个参数时,slice() 方法返回从该数组指定位置开始到当前数组末尾的所有的项。两个参数时,会返回数组从起始位置和结束位置之间的项。该方法不会影响原数组。


let names = ['zhangsan', 'lisi', 'wangwu', 'zhaoliu', 'houqi']
let names2 = names.slice(1)
let names3 = names.slice(1, 3)

console.log(names2) // ['lisi', 'wangwu', 'zhaoliu', 'houqi']
console.log(names3) // ['lisi', 'wangwu']

11.concat()方法
12.indexOf()方法

说明:返回获取项在数组中第一次出现的索引


let names = ['zhangsan', 'lisi', 'wangwu', 'lisi']
let index = namse.indexOf('lisi')

console.log(index) // 1

// 这里打印的是1,而不是3,说明 indexOf() 方法,返回传入项的第一次出现的索引

13.lastIndexOf()方法

说明:返回获取项在数组中最后一次出现的索引


let names = ['zhangsan', 'lisi', 'wangwu', 'lisi']
let index = namse.lastIndexOf('lisi')

console.log(index) // 3

// 这个和 indexof() 相对

(二)数组遍历

接下来是一些常用的数组遍历方法

1.forEach()

说明: 遍历数组中的每一项,对每一项运行给定函数,该方法没有返回值

2.some()

说明:遍历数组中的每一项,对每一项运行给定函数,如果该函数任意一项返回true,则返回true


let values = [1, 2, 6, 35, 46]
let flag = values.some((item, index, array) => {
  return item > 10
})

console.log(flag) // true

3.every()

let values = [1, 2, 6, 35, 46]
let flag = values.every((item, index, array) => {
  return item > 10
})

console.log(flag) // false

4.find()

说明:找到符合条件的数组中的项,并立即结束循环,返回该项


let values = [1, 2, 6, 35, 46]
let newValue = values.find((item, index, array) => {
  return item > 10
})

console.log(newValue) // 35

5.findIndex()

说明:找到符合条件的数组中的项,并立即结束循环,返回该项的索引


let values = [1, 2, 6, 35, 46]
let newValue = values.findIndex((item, index, array) => {
  return item > 10
})

console.log(newValue) // 3

6.filter()

说明:遍历数组中的每一项,对每一项运行给定函数,返回该函数为 true 的数组。


let values = [1, 2, 6, 35, 46]
let newValues = values.filter((item, index, array) => {
  return item > 10
})
console.log(newValue) // [35, 46]

7.map()

说明:遍历数组中的每一项,对每一项运行给定函数,返回每次函数调用结果后组成的数组。


let values = [1, 2, 6, 35, 46]
let newValues = values.map((item, index, array) => {
  return item + 1
})
console.log(newValue) // [2, 3, 7, 36, 47]

8.reduce()

说明:对数组中的每一个元素执行一个自定义累加器,将其结果汇总为单个返回值。

这样解释可能有些不好理解,接下来有例子,一看就明白了。reduce() 是数组操作中最强大的方法,也是最好用的方法!(非常重要!!!),为什么这么说呢,因为它可以实现上述介绍的所有方法!

它可以接收两个参数,一个是在每一项上都会调用的函数,一个是称为累加(或归并)基础的初值!第二个参数是可选的。

第一个参数作为函数,它可以接收四个参数,分别是:前一个值、当前值、当前项的索引和数组本身。一如既往,我们直接上例子:

将数组累加


let values = [1, 2, 3, 4, 5]

let sum = values.reduce((pre, cur, index, array) => {
  return pre + cur
})

console.log(sum) // 15


reduceRight() 方法和 reduce() 方法一样,只不过一个是正序,一个是倒序!

(三)实际案例

接下来就用一些实际的例子,让大家看下同一个需求,不同的写法,择优而用!

  • 取一个长度为 100 的数组,并保证每一项为 0~1000 的随机整数

// 方法一 Array.from() 方法
let values1 = Array.from(Array(100), (item,index) => parseInt(Math.random()*1000))

// 方法二 用 fill 方法
let values2 = new Array(100).fill(0).map(() => parseInt(Math.random()*1000)))

// 方法三
let values3 = [...Array(100).map(() => parseInt(Math.random()*1000))]

注意:new Array() 会生成一个有100空位的数组,这个数组不能被 map(), forEach(), filter(), every(), some() 遍历的,因为空位会被跳过(for of 不会被跳过,可以遍历)。
[…Array(100)] 可以给空位设置默认值 undefined ,从而可以被上述方法遍历。

我再也不想看到下面这样的代码:


let values = []
for(let i = 0;i < 100;i++){
  let val = parseInt(Math.random()*1000)
  values.push(val)
}

  • 数组合并

let values1 = Array.from(Array(100), (item,index) => parseInt(Math.random()*1000))
let values2 = new Array(100).fill(0).map(() => parseInt(Math.random()*1000)))
let values3 = [...Array(100).map(() => parseInt(Math.random()*1000))]

// 方法一
values1.concat(values2, values3)

// 方法二
let values = [...values1, ...values2, ...values3]

  • 数组去重

let values = [1, 1, 2, 3, 3, 4, 5, 5]
let newValues = [...new Set(values)];

console.log(newValues) // [1,2,3,4,5]

new Set() 方法接收一个数组参数,并生成一个 set 结构的数据类型,set 数据类型的元素不会重复,且是 Array Interator,利用这一特性可以去重。

当然,如果你愿意用下面的方法的话,那就随心就好:


let values = [1, 1, 2, 3, 3, 4, 5, 5]
let newValues = []
for(let i = 0;i < values.length;i++) {
  if(newValues.indexOf(values[i]) < 0) {
    newValues.push(values[i])
  }
}

console.log(newValues) // [1,2,3,4,5]

  • 数组取交集

let values1 = [0,1,2,3,4,5,6]
let values2 = [3,4,5,6,7]
let duplicValues = [...new Set(values1)].filter(item => values2.includes(item));

console.log(duplicValues) // [3,4,5,6]

  • 数组取差集

let values1 = [0,1,2,3,4,5,6]
let values2 = [3,4,5,6,7]
let duplicValues = [...new Set([...values1,...values2])].filter(item => !values1.includes(item) || !values2.includes(item));

console.log(duplicValues) // [0,1,2,7]

当然,看到这里的小伙伴会说:“实际项目中哪有数组都是数字的?基本都是对象数组!”是的,这个确实是事实,那接下来我就举一些对象数组的例子

  • 去重

我们以id的维度去重


let persons = [
  {id:1,name:'Jack',age:18,sex:'男'},
  {id:2,name:'Kevin',age:21,sex:'男'},
  {id:3,name:'Jessica',age:23,sex:'女'},
  {id:4,name:'Sarah',age:19,sex:'女'},
  {id:2,name:'Kevin',age:21,sex:'男'},
]
let unique = {};
let arr = persons.reduce((pre, cur) => {
  unique[cur.id] ? '' : unique[cur.id] = true && pre.push(cur)
  return pre
},[])


上面用的是万能而又强大的 reduce() 方法,当然你也可以这么写,结果是一样的:


let persons = [
  {id:1,name:'Jack',age:18,sex:'男'},
  {id:2,name:'Kevin',age:21,sex:'男'},
  {id:3,name:'Jessica',age:23,sex:'女'},
  {id:4,name:'Sarah',age:19,sex:'女'},
  {id:2,name:'Kevin',age:21,sex:'男'},
]

const unique = function(array, key) {
  let resultArr = []
  let paramsArr = array.map(item => item[key])
  let newArr = [...new Set(paramArr)]
  newArr.forEach(item1 => {
    for(let j = 0;j < array.length;j++) {
      if(item1 === array[j][key]) {
        resultArr.push(array[j])
        break;
      }
    }
  })
  return resultArr;
}

console.log(unique(persons, 'id'))

文章到这里就结束了,当然也有很多不足或者很多操作有更简洁的方法,希望大佬们批评指正,鉴于我把 reduce() 方法吹嘘的神乎其神,后续我会专门整理一个 reduce() 方法的介绍和它强大的应用


谢谢!

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值