数组相关文章:
数组去重的 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) // true
const 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
实现。
评论