阅读 681

一段JS的Array评测之旅(休闲娱乐划水伴侣)

前言

当清晨的第一缕阳光,映照在我脸庞。犹如一双饱含温情的手抚摸着抚摸着,我便起了床。雨水洗刷过的街道,弥漫着沁人心脾的清香。 街边早餐铺的油条在锅中滋滋发出声响,我知道这根热气腾腾新鲜出炉的油条,过一会儿将会去到下一个地方。我三两口就送它去了(就像B站美食up主徐大sao在重庆时的狠话二两面我两口就吃完了)我便来到了早晨的第一个打卡点,地铁站🚞。车厢内真是人山人海挨肩擦背一点都不夸张,有时停站耳边也会传来工作人员的呐喊声(挤嘛,这儿还可以qi一个)下了车也是人头攒动步履艰辛。在车厢里结伴同行的人很少,大家都习惯低着头看着手机这让我想起了一句话抬头看见梦想,低头却碰见了现实我也闭上了双眼开始陷入沉思🤔,JS的数组api中属于遍历的有很多,它们各司其职。但是真正的使用场景是什么?哪一个在场景中性能更高,更快?便有了下文。

有看面试相关的小伙伴可以浏览下好朋友正在火热筹划中的 面试汇总库💪

若文章中的解答有误,希望能够得到小伙伴们的指正与谅解。希望能和你来一场知识的碰撞。

在计算之前,我需要一个计算运行时间函数,和一个实验测试数组arr

function calcTime (func) {
 let start = new Date().getTime(); //开始时间
 func();                           //执行待测函数
 var end = new Date().getTime();   //结束时间
 return (end - start)+ "ms";       //返回函数执行需要时间
}

let arr = []                    // 创建一个我需要的测试数据
for(let i=0;i<1000000;i++) {
  arr.push(i)
}
复制代码

Array 遍历API

find()

find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。

我现在有一个需求,从一个数组中,找出指定项。

// 使用find前
function foo(){
  for(let i=0;i<arr.length;i++){
    if(arr[i] === 50000) return;
  }
}
//使用find后
function findFoo(){
  arr.find( item => item === 50000)
}
calcTime(foo)    // 16ms 
calcTime(findFoo)   // 1ms  find更优
复制代码

本次实验环境是在JSBin保证了环境相同,设备相同,情景相同,所有实验结果都会会根据你的电脑性能给出不同值。所以不要考虑绝对值,参考点是在相对值👆。

forEach,map

forEach() 方法对数组的每个元素执行一次提供的函数。

map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

为了避免JSBin崩溃,本次arr长度为1w

function foo(){
  for(let i=0;i<arr.length;i++){
    for(let j=0;j<arr.length;j++){}
  }
}
// 使用forEach
function foreachFoo(){
  arr.forEach(()=>{
    arr.forEach(()=>{})
  })
}
// 使用map
function fooMap(){
  arr.map(()=>{
    arr.map(()=>{})
  })
}
calcTime(foo)           // 39ms 
calcTime(foreachFoo)    // 649ms 
calcTime(foreachMap)    // 699ms  for()更优
复制代码

filter

filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。本次arr长度10w

function foo(){
    let newArr =[]
  for(let i=0;i<arr.length;i++){
    if(arr[i]>=50000){
      newArr.push(arr[i])
    }
  }
}
// 使用filter
function filterFoo(){
  letnewArr = arr.filter(item=> item>=50000 )
}

calcTime(foo)           // 59ms 
calcTime(filterFoo)    // 4ms    filter更优 
复制代码

reduce

reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

function foo(){
  let sum = 0
  for(let i=0;i<arr.length;i++){
    sum = sum + arr[i]
  }
}
// 使用reduce
function reduceFoo(){
  arr.reduce((sum,item)=>sum +item)
}

calcTime(foo)           // 57ms
calcTime(reduceFoo)     // 4ms  reduce更优
复制代码

通过简单的几个对比,可以知道数组中创造filter,find,reduce都是有目的。还是俗话说的好,术业有专攻。我们作为开发者首先应该知道每个api的作用,然后考虑自己的业务场景选择最佳的方法。 举个🌰

前天看到一位掘友发的一个沸点

以前的写法:

iconFliter(num){
    if(num>0 && nun<=30){
      return 'normal'     
    }
    if(num>30 && nun<=100){
      return 'orange'
    }
    if(num>100 && nun<=250){
      return 'yellow'     
    }
    if(num>250){
        return 'red'
    }
复制代码

这样写并没有问题,但是我们可以仔细思考下,我们可以借用现有的数据结构(对象,数组)他们的特点来完成,如下

// 业务中独立的变量转化成数组和对象结构
let datas = [{time:30,color:'normal'},{time:100,color:'orange'},{time:250,color:'yellow'}]

// 再通过高效的api进行处理
function iconFilter(num,data) {
	if (num<0) return 
   	let selectData =  data.find(item => num <= item.time)
   	return selectData ? selectData.color:'red' 
}
复制代码

只要多思考,代码肯定会越写越好。

数组总结

返回Boolean的方法

方法名 描述
some 检测数组元素中是否有元素符合指定条件
every 检测数值元素的每个元素是否都符合条件。
includes 判断一个数组是否包含一个指定的值。

修改原数组的方法(面试中经常被问起)

方法名 描述
push 向数组的末尾添加一个或更多元素,并返回新的长度
pop 删除数组的最后一个元素并返回删除的元素
unshift 向数组的开头添加一个或更多元素,并返回新的长度
shift 删除并返回数组的第一个元素
reverse 反转数组的元素顺序
splice 从数组中添加或删除元素
sort 对数组的元素进行排序

剩下的方法就是不改变原数组的方法

一道题

平时业务中经常会对后端小伙伴返回的数组对象进行处理,此时我需要将citizenship(国籍)为china的对象属性name换成chineseName,新增一个属性location值为Asian,国籍为america也要进行操作,你会怎么做?如下所示吗?平时你就是这种写的吗?

let datas = [{name:'张大娃',age:19,sex:'boy',citizenship:'china'},
        {name:'张老二',age:35,sex:'boy',citizenship:'china'},
        {name:'赵二娃',age:21,sex:'boy',citizenship:'china'},···]
datas.forEach(item=>{
    if(item.citizenship === 'china'){
        item.chineseName = item.name
        item.location = 'Asian'
    }else if (item.citizenship === 'America') {
        item.americaName = item.name
        item.location = 'northAmerica'
    }
})
复制代码

希望你能帮我优化一下上面的代码

马上就要打下班卡领取周末了,祝大家周末愉快天天开💓

关注下面的标签,发现更多相似文章
评论