数组相关文章:
数组去重的 7 种算法
找出数组中出现次数最多元素的 4 种算法
数组遍历的 7 种方法及兼容性处理 (polyfill)
数组的遍历在数组的所有操作中应该是最频繁的,这里总结下 7 中常见的遍历方法。同时,通过 polyfill 理解每个函数的内部实现。
1. 最原始的 for 循环
const arr = [1,2,3]for(let i=0;i<arr.length;i++){ console.log(arr[i])}
复制代码
2. 基于 forEach()函数的方法
const arr = [1,2,3]arr.forEach(function(element,index,array){ console.log(element)})
复制代码
forEach()函数是 ES5 中新增的特性,可能不兼容只支持低版本 JS 的浏览器,因此提供个pollyfill。
Array.prototype.forEach = Array.prototype.forEach || function(fn,context){ // 通过for循环,在循环中判断this对象,即数组本身是否包含遍历的索引。 // 包含,则利用call()函数去调用回调函数,传入回调函数所需的参数。 if(typeof fn==='function'){ for(var k=0,length=this.length;k<length;k++){ Object.prototype.hasOwnProperty.call(this,k) && fn.call(context,this[k],k,this) } }}
复制代码
3. 基于 map()函数的方法
map()在数据遍历中,将数组中的每个元素做处理,得到新的元素。需要注意的是回调函数需要通过return返回处理后的值,否则会返回undefined。
const arr = [1,2,3]const arr1 = arr.map(function(element){ return element*2})console.log(arr1) // [2,4,6]
复制代码
同forEach()函数一样,map()同样需要提供polyfill。
Array.prototype.map = Array.prototype.map || function(fn,context){ var arr = [] if(typeof fn==='function'){ for(var k=0,length=this.length;k<length;k++){ if(Object.prototype.hasOwnProperty.call(this,k)){ arr.push(fn.call(context,this[k],k,this)) } } } return arr}
复制代码
4. 基于 filter()函数的方法
filter()函数用于过滤出满足条件的数据,返回一个新的数组,不会改变原来的数组。
const arr = [1,2,3,4]const filterFn = function(element){ return element>2}const arr1 = arr.filter(filterFn) // [3,4]
复制代码
polyfill代码如下:
Array.prototype.filter = Array.prototype.filter || function(fn,context){ var arr = []; if(typeof fn==='function'){ for(var k=0,length=this.length;k<length;k++){ if(Object.prototype.hasOwnProperty.call(this,k)){ // 通过判断返回值是否为true来决定是否push到新数组 fn.call(context,this[k],k,this) && arr.push(this[k]) } } } return arr}
复制代码
5. 基于 some()和 every()函数的方法
some()函数只要数组中某个元素满足条件就返回true,而every()函数需要数组中的每个元素都满足条件时才返回true。
function isBig(element,index,array){ return element>2}
const passed1 = [1,2,3,4].some(isBig) // trueconst passed2 = [1,2,3,4].every(isBig) // false
复制代码
some()函数的pollyfill如下:
Array.prototype.some = Array.prototype.some || function(fn,context){ var passed = false if(typeof fn==='function'){ for(var k=0,length=this.length;k<length;k++){ if(passed===true) break; // 有返回值true,直接跳出循环 passed = Object.prototype.hasOwnProperty.call(this,k)? !! fn.call(context,this[k],k,this):passed } } return passed}
复制代码
every()函数的pollyfill如下:
Array.prototype.every = Array.prototype.every || function(fn,context){ var passed = true if(typeof fn==='function'){ for(var k=0,length=this.length;k<length;k++){ if(passed===false) break; // 有返回值false,直接跳出循环 passed = Object.prototype.hasOwnProperty.call(this,k)? !! fn.call(context,this[k],k,this):passed } } return passed}
复制代码
6. 基于 reduce()函数的方法
reduce()函数主要作用是做累加处理,即接收一个函数作为累加器。
arr.reduce(callback[,initialValue]);
callback 接收四个参数:accumulator、currentValue、currentIndex、array
initialValue:作为 callback 的第一个参数值,若未设置,则默认使用数组的第一个元素值。
accumulator: 表示上一次调用累加器的返回值,或设置的initialValue。
let arr = [1,2,3]let add = function(accumulator,currentValue){ return accumulator+currentValue}let sum = arr.reduce(add,0) // 6
复制代码
reduce()函数的 polyfill 如下:
Array.prototype.reduce = Array.prototype.reduce || function(callback,initialValue){ var previous = initialValue,k = 0, length = this.length; if(typeof initialValue === 'undefined'){ previous = this[0] k = 1 } if(typeof callback === 'function'){ for(k;k<length;k++){ this.hasOwnProperty(k) && (previous = callback(previous,this[k],k,this)) } } return previous}
复制代码
7. 基于 find()函数的方法
find()函数用于数组遍历的过程中,找到第一个满足条件的元素值时,则直接返回该元素值;如果都不满足条件,则返回undefined。
let arr = [1,2,3]let value = arr.find(function(element,index,array){ return element>2}) // 3
复制代码
find()函数的 polyfill 如下:
Array.prototype.find = Array.prototype.find || function(fn,context){ if(typeof fn==='function'){ for(var k = 0,length = this.length;k < length;k++){ if(fn.call(context,this[k],k,this)){ return this[k] } } } return undefined}
复制代码
8. 总结
至此我们完成了 7 个与函数遍历相关的方法,以及它们的polyfill实现。
评论