资讯专栏INFORMATION COLUMN

JS 数组循环遍历方法的对比

BlackFlagBin / 3283人阅读

摘要:循环方法方法不改变原数组方法会给原数组中的每个元素都按顺序调用一次函数。筛选出过滤出数组中符合条件的项组成新数组代码方法方法为数组中的每个元素执行一次函数,直到它找到一个使返回表示可转换为布尔值的值的元素。

前言

JavaScript 发展至今已经发展出多种数组的循环遍历的方法,不同的遍历方法运行起来那个比较快,不同循环方法使用在那些场景,下面将进行比较:

各种数组遍历的方法 for 语句

代码:

var arr = [1,2,4,6]
for(var i = 0, len = arr.length; i < len; i++){
    console.log(arr[i])
}

这是标准for循环的写法也是最传统的语句,字符串也支持,定义一个变量i作为索引,以跟踪访问的位置,len是数组的长度,条件就是i不能超过len。

forEach 语句

forEach 方法对数组的每个元素执行一次提供的CALLBACK函数,forEach是一个数组方法,可以用来把一个函数套用在一个数组中的每个元素上,forEach为每个数组元素执行callback函数只可用于数组.遍历一个数组让数组每个元素做一件事情.那些已删除(使用delete方法等情况)或者未初始化的项将被跳过(但不包括那些值为 undefined 的项)(例如在稀疏数组上);不像map() 或者reduce() ,它总是返回 undefined值,并且不可链式调用。典型用例是在一个链的最后执行副作用。

代码:

var arr = [1,5,8,9]
arr.forEach(function(item) {
    console.log(item);
})
for-in 语句

一般会使用for-in来遍历对象的属性的,不过属性需要 enumerable,才能被读取到.
for-in 循环只遍历可枚举属性。一般常用来遍历对象,包括非整数类型的名称和继承的那些原型链上面的属性也能被遍历。像 Array和 Object使用内置构造函数所创建的对象都会继承自Object.prototype和String.prototype的不可枚举属性就不能遍历了.

代码:

var obj = {
    name: "test",
    color: "red",
    day: "sunday",
    number: 5
}
for (var key in obj) {
    console.log(obj[key])
}
for-of 语句 (ES 6)

for-of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。只要是一个iterable的对象,就可以通过for-of来迭代.

代码:

var arr = [{name:"bb"},5,"test"]
for (item of arr) {
    console.log(item)
}
for-offor-in 的区别

for-in 语句以原始插入顺序迭代对象的可枚举属性。for-in会把继承链的对象属性都会遍历一遍,所以会更花时间.

for-of 语句只遍历可迭代对象的数据。

Other 循环方法 map 方法 (不改变原数组)

map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。 callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。让数组通过某种计算产生一个新数组,影射成一个新的数组,

代码:

var arr = [1,2,3]
var firearr = arr.map(current => current * 5)
reduce 方法

让数组中的前项和后项做某种计算,并累计最终值,

代码:

var wallets = [4,7.8,3]
var totalMoney = wallets.reduce( function (countedMoney, wallet) {
    return countedMoney + wallet.money;
}, 0)
filter 方法 (不改变原数组)

filter 为数组中的每个元素调用一次 callback 函数,并利用所有使得 callback 返回 true 或 等价于 true 的值 的元素创建一个新数组。callback 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 callback 测试的元素会被跳过,不会被包含在新数组中。筛选出过滤出数组中符合条件的项,组成新数组.

代码:

var arr = [2,3,4,5,6]
var morearr = arr.filter(function (number) {
    return number > 3
})
every 方法

every 方法为数组中的每个元素执行一次 callback 函数,直到它找到一个使 callback 返回 false(表示可转换为布尔值 false 的值)的元素。如果发现了一个这样的元素,every 方法将会立即返回 false。否则,callback 为每一个元素返回 true,every 就会返回 true。检测数组中的每一项是否符合条件,如果每一项都符合条件,就会返回true,否则返回false,有点像遍历数组且操作callback。只会为那些已经被赋值的索引调用。不会为那些被删除或从来没被赋值的索引调用。

代码:

var arr = [1,2,3,4,5]
var result = arr.every(function (item, index) {
    return item > 0
})
some 方法

some 为数组中的每一个元素执行一次 callback 函数,直到找到一个使得 callback 返回一个“真值”(即可转换为布尔值 true 的值)。如果找到了这样一个值,some 将会立即返回 true。否则,some 返回 false。callback 只会在那些”有值“的索引上被调用,不会在那些被删除或从来未被赋值的索引上调用。检查数组中是否有某些项符号条件,如果有一项就返回true,否则返回false,有点像遍历数组或者操作.

代码:

var arr = [1,2,3,4,5]
var result = arr.some(function (item,index) {
    return item > 3
})
对比遍历速度

对比这里我使用了jsPerf平台进行测试.

JavaScritp loop 对比

我创建了两个数组进行对比,为什么要这样区别呢,因为不同类型的数组在javascript内存中保存的地址格式不一样,遍历的时候编辑器会根椐数组元素的类型长度计算,比如说如果数组里面全是Number类的,循环起来会比数组里面包含Number,String,Object混合型的会快,所以创建了两个数组,一个是全undefined数组,一个是混合型数组.

// 一个是空数组
var nullarr = new Array(10000) // [undefined,undefined,...undefined]

// 另一个带不同类型的数据的数组
var dataarr = []
for(var i = 0; i < 10000; i++){
    if (i % 2 ===0) {
        dataarr[i] = i.toString()
    } else {
        dataarr[i = i
    }
}
dataarr // [1,"2",3...,10000]

测试后发现有点奇怪直接检索空数组还是会比数据数组慢这是为什么呢奇怪?为了对比循环的一致性我只选其中带数据的数组dataarr进行测试.

那我们对比一下 for for len forEach for-in for-of map filter 循环的速度

可以看到 for循环的速度是最快的,是最老的循环,也是优化得最好的,其次是for-of这个是es6才新增的循环非常好用,最慢是for-in我们可以作一下速度排序

for > for-of > forEach > filter > map > for-in

这很明显处理大量循环数据的时候还是要使用古老for循环效率最好,但也不是不使用for-in,其实很多时候都要根据实际应该场景的,for-in更多使用在遍历对象属性上面,for-in在遍历的过程中还会遍历继承链,所以这就是它效率比较慢的原因,比如map 速率不高,不过处理在Es6实现数组功能上面非常好用方便,轻松影射创建新数组.或者例如使用Iterator属性也是行的,所以每个循环都有合适使用的地方.

everysome 不完全属于数组操作方法

everysome 都是判断条件直接返回整个数组Boolean类型的方法.every速度会比some快很多.

干货

一张图展示JavaScript数组方法

最后

最后不同浏览器内核我相信会有些许差别,有兴趣的朋友可以去测试一下,有任何问题欢迎给博主留言.更多好文章请到我博客地址 浏览哈。

最后附上上面循环测试的 地址

延伸阅读

迭代器(iterator) 地址

JS几种数组遍历方式以及性能分析对比 地址

如何形象地解释 JavaScript 中 map、foreach、reduce 间的区别? 地址

For-each over an array in JavaScript? 地址

JavaScript for循环性能比较 地址

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107043.html

相关文章

  • js数组遍历总结

    摘要:中的数组遍历是项目中经常用到的,在这里将几种方法做个对比。第一个参数为数组元素必选,第二个参数为数组元素索引值可选,第三个参数为数组本身可选循环中传入要执行的回调函数,函数有三个参数。用于遍历数组元素使用,,,用于循环对象属性使用 js中的数组遍历是项目中经常用到的,在这里将几种方法做个对比。 for循环:使用评率最高,也是最基本的一种遍历方式。 let arr = [a,b,c,d,...

    oujie 评论0 收藏0
  • 数组常见遍历循环方法数组循环遍历效率对比

    摘要:场景检查数组中是否含有某个东西和是对立的案例案例是否包含为对象循环遍历效率对比参考参考原生实现等方法其他参考 1 遍历数组的方法 1-1、for / while 最普通的循环 效率最高 兼容ie6tips:for循环更适用于循环的开始和结束已知,循环次数固定的场合;while循环更适合于条件不确定的场合 1-2、for in 兼容ie6,效率最差(效率可看最下面的对比) for in...

    xfee 评论0 收藏0
  • Deep In React 之详谈 React 16 Diff 策略(二)

    摘要:对于同一层级的一组子节点,它们可以通过唯一进行区分。基于以上三个前提策略,分别对以及进行算法优化。链表的每一个节点是,而不是在之前的虚拟节点。是当前层的第一个节点。再次提醒,是的一层。 文章首发于个人博客 这是我 Deep In React 系列的第二篇文章,如果还没有读过的强烈建议你先读第一篇:详谈 React Fiber 架构(1)。 前言 我相信在看这篇文章的读者一般都已经了解...

    NSFish 评论0 收藏0
  • js之灵活使用可遍历数组API

    摘要:总结遍历数组的时候应该尽量使用这些,灵活运用可以让代码更加优雅,这种尽可能使用函数和链式调用的风格很接近函数式编程,可以提高代码质量。 js中有很多可以遍历数组的API,既然已经封装的这么好,为什么不在平常开发的时候使用,本文讲讲forEach、map、filter、some、every、reduce这些API的使用,并且和普通的for语句作对比。 我们以一个对象数组作为测试数据: c...

    sutaking 评论0 收藏0
  • JS中可能用得到全部排序算法

    本篇有7k+字, 系统梳理了js中常见的12种排序算法。除了基本排序算法,文章还包含了希尔排序、堆排序、桶排序等较为复杂的排序实现,如果喜欢请点赞支持~谢谢. 原文: http://louiszhai.github.io/20... 导读 排序算法可以称得上是我的盲点, 曾几何时当我知道Chrome的Array.prototype.sort使用了快速排序时, 我的内心是奔溃的(啥是快排, 我只知道...

    verano 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<