js数组方法(es5)
ECMAScript 5定义了9个新的数组方法来遍历、映射、过滤、检测、简化和搜索数组。下面几节描述了这些方法。
但在开始详细介绍之前,很有必要对ECMAScript 5中的数组方法做一个概述。首先,大多数方法的第一个参数接收一个函数,并且对数组的每个元素(或一些元素)调用一次该函数。如果是稀疏数组,对不存在的元素不调用传递的函数。在大多数情况下,调用提供的函数使用三个参数:数组元素、元素的索引和数组本身。通常,只需要第一个参数值,可以忽略后两个参数。大多数ECMAScript 5数组方法的第一个参数是一个函数,第二个参数是可选的。如果有第二个参数,则调用的函数被看做是第二个参数的方法。也就是说,在调用函数时传递进去的第二个参数作为它的this关键字的值来使用。被调用的函数的返回值非常重要,但是不同的方法处理返回值的方式也不一样。ECMAScript 5中的数组方法都不会修改它们调用的原始数组。当然,传递给这些方法的函数是可以修改这些数组的。
forEach
forEach方法用于遍历数组,并进行相应操作。它有一个必填参数,这个参数是一个回调函数,这个函数有3个参数,依次是:当前遍历到的数组元素(item)、当前的数组元素的索引值(index)、当前操作的数组对象(curArr);后两个参数可选,第一个参数必填,这个回调函数没有返回值。
var arr1 = [1,2,3,4,5]; arr1.forEach((item, index, curArr) => { curArr[index] = item*item; }); // arr1 //[1, 4, 9, 16, 25]
forEach方法会改变原数组,而且它不会提前终止遍历,即会把数组的每一项都遍历之后才会结束运行,所以即使报错也不会终止该方法,需要把forEach方法放到一个try代码块中,并能抛出一个异常,如果forEach方法调用的函数抛出foreach.break异常,那么遍历会终止。
map
map方法与forEach方法很相似,它有一个回调函数,回调函数有三个参数,1个必填,2个可选,依次是item、index、curArr。不同的是,map的回调函数应该有返回值。
如果map的回调函数的 return 后面是一个变量表达式,那么map方法的返回值是进行对应操作后的新数组
var arr2 = [1, 2, 3, 4, 5]; var newArr1 = arr2.map((item,index,curArr)=>item * item); // 不加花括号是直接返回 => 后的值,当前数组的每一项都进行平方操作 // [1, 4, 9, 16, 25] // arr2 // [1, 2, 3, 4, 5]
如果map的回调函数的 return 后面是一个条件表达式,那么map方法的返回值是由当前数组的每一项对该条件的判定结果为true或false的数组项组成的子数组。
var arr2 = [1,2,3,4,5]; arr2.map(item => item<3) //[true, true, false, false, false]
还有一点与forEach方法不同的是,map方法不会改变原数组
filter
filter方法的参数结构跟 map 方法相似,不同的是,它的返回值是原数组的一个子数组,该子数组里面的数组项的属性值满足回调函数里的条件,即 filter 方法的返回值是由当前数组的每一项对该条件的判定结果为true时的数组项组成的子数组。
var arr3 = [1, 2, 3, 4, 5, 6, 7, 8, 9]; var newArr2 = arr3.filter((item,i,curArr)=>item < 6); // [1, 2, 3, 4, 5] // arr3 // [1, 2, 3, 4, 5, 6, 7, 8, 9]
filter方法还有一个特征是,filter不会遍历稀疏数组,也就是说,被省略的数组元素会被过滤掉,不参与条件判定,所以,filter返回的数组是一个密集数组。
var arr3 = [1,2,3,undefined,null,,,]; var newArr2 = arr3.filter((item, i, curArr) => { return item; }); // [1,2,3] 说明filter方法只会返回稠密数组,会过滤掉undefined和null
filter方法不会修改原数组。
every && some
every方法返回的是一个布尔值,当遍历的目标数组中的每一项都满足回调函数中的条件时才返回true,否则返回false,和逻辑运算中的“与”运算原理一致,一假则假。而且,every方法与forEach方法不同的是,every方法在运行到可以确定返回值的时候就会提前结束遍历。
var arr4 = [1,2,3,4,5]; var temp1 = []; var result = arr4.every(item => { temp1.push(item); return item<3 }); // false console.log(temp1); // [1,2,3] 说明遍历到3,就不满足条件,然后停止遍历了
some方法与逻辑运算中的“或”运算原理一样,一真即真。也就是说,只要目标数组中有一个元素满足了回调函数中的条件,就返回true,只有全部都不满足时才返回false。some方法与every方法的遍历规则一样,只要能够确定返回值了就立刻终止遍历。
var temp2 = []; var result2 = arr4.some(item => { temp2.push(item); return item<3 }); // true console.log(temp2); // [1] 说明遍历到1,就满足了条件,于是停止遍历
注意,当every和some方法的目标数组是一个空数组时,every方法返回的是true,some方法返回的是false
console.log([].every(item=>item)); // true console.log([].some(item=>item)); //false
reduce && reduceRight
reduce方法和reduceRight方法使用指定的函数将数组元素组合,生成单个值。
reduce方法需要两个参数,第一个参数是执行化简操作的函数,化简函数的任务就是用某种方法把两个值组合或化简为一个值,并返回这个化简之后的值;第二个参数是执行化简操作的初始值,是一个可选参数,如果不写,则默认为数组的第一个元素。
var arr5 = [1,2,3,4,5]; var result3 = arr5.reduce((a,b) => a+b); // 15 (((1+2)+3)+4)+5
两个数组元素为一组进行化简操作,最后得到的一个化简值又作为下一次化简操作的第一个操作数,以此类推,上述代码的功能就是对arr5数组里的元素做累加操作。
reduceRight方法与reduce方法其实是一样的,但是他的化简操作是从右往左实现的。
[1,6,3,12].reduceRight((a,b)=> {return a-b}) // 2 // ((12-3)-6)-1
值得注意的是,reduce方法和reduceRight方法再目标数组是一个空数组的情况下,第二个参数写与不写的结果是有很大区别的。
当不写第二个参数时,会报错:
[].reduce((a,b) => a+b) // 报错 VM2095:1 Uncaught TypeError: Reduce of empty array with no initial value [].reduce((a,b) => a+b,1) // 1
indexOf && lastIndexOf
indexOf()和lastIndex0f()搜索整个数组中具有给定值的元素,返回找到的第一个元素的索引或者如果没有找到就返回-1。indexOf()从头至尾搜索,而lastIndexOf()则反向搜索。
a = [0,1,2,1,0]; a.index0f(1) // 1, a[1]是1 a.lastIndexOf(1) // 3, a[3]是1 a.indexOf(3) // -1, 没有值为3的元素
不同于上面描述的其他方法,indexOf()和lastIndexOf()方法不接收一个函数作为其参数。第一个参数是需要搜索的值,第二个参数是可选的:它指定数组中的一个索引,从那里开始搜索。如果省略该参数,index0f()从头开始搜索,而lastIndexOf()从末尾开始搜索。第二个参数也可以是负数,它代表相对数组末尾的偏移量,对于splice()方法:例如,-1指定数组的最后一个元素。