JS-数组方法forEach

774 阅读1分钟

重要数组的方法有哪些

  1. forEach:用于遍历数组,没有返回值,可以对遍历出的数组项进行后续操作
  2. filter:用于遍历数组,且筛选出符合条件的数组项,可以对筛选出的数组项进行后续操作
  3. every:需要在回调函数中使用return true/false来返回单圈的执行,当所有都true才返回最终的true,否则返回false
  4. some:和every差不多的原理和使用,最终返回布尔值,只要有一次循环为true,则true
  5. reduce:(后续添加)

本篇章主要对forEach进行解析,一个例子,一个手写myForEach

本篇章不对其他函数做笔记,手写方式大同小异,reduce有所区别,后续补充

forEach

一、使用说明

在目标数组arr遍历出数组的每一项currentValue,在回调函数中操作数组项等

格式: 目标数组.forEach(function(currentValue, index, arr) {

},thisValue)

参数:

currentValue:数组项

index:数组下标

arr:目标数组本身

thisValue:this指向的目标,不填则指向window

二、例子

将arr数组的name用无序列表方式呈现到页面中

<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>
let arr = [
    {"id":1,"name":"zanshan","sex":"m"},
    {"id":2,"name":"lisi","sex":"w"},
    {"id":3,"name":"wangwu","sex":"m"},
]
arr.forEach(function(ele,index,taget) {
    //console.log(ele,index,taget,this)
    this[index].innerHTML = ele.name
},document.getElementsByTagName("li"))

例子说明: 第二个参数的传入使得this的指向document.getElementsByTagName("li"),所以可以直接操作this来操作dom树,在li标签中添加名字。

三、手写MyForEach

先附代码

let arr = [
    {"id":1,"name":"zanshan","sex":"m"},
    {"id":2,"name":"lisi","sex":"w"},
    {"id":3,"name":"wangwu","sex":"m"},
]
//MyForEach内容
Array.prototype.MyForEach = function(fun){
    let _arr = this,length = _arr.length,pram2 = arguments[1]||window
    for(let i = 0;i<length;i++){
        fun.call(pram2,_arr[i],i,_arr)
    }
}
//测试MyForEach和forEach是否功能上一致
arr.MyForEach(function(ele,index,taget) {
    console.log(ele,index,taget,this)
    this[index].innerHTML = ele.name
},document.getElementsByTagName("li"))

注意: 测试MyForEach使用箭头函数,第二个参数就失效了

手写原理

1. 需要将taget指代对象arr,所以在API实现内部将this传给回调函数fun的第三个参数(由于此处使用到了call,所以表现为第四个参数),通过_arr=this,后将_arr传递进fun
2. 通过_arr.length获取到循环的总次数
3. call改变了调用fun方法的this指向,如果不传递MyForEach的第二个参数,则默认是window在调用fun函数,在API使用时,打印this,this就是window;如果传递MyForEach的第二个参数,在API使用时,打印this,this就是MyForEach的第二个参数,通过操作this,来操作dom
4. 对上面的两个this进行说明,一个是指向arr的,一个是fun的调用者,两者有啥区别:前者的this环境是MyForEach函数刚进去,遵循谁调用则指向谁,因此测试MyForEach时,arr.MyForEach就象征着this指向了MyForEach;后者this环境是fun函数的。以上即使区别

-----------------------------------分割线 更改时间2021.7.19--------------------------------------

Array.prototype.myForEach = function(callback){
    let currentValue,index,array = this
    let thisArg = arguments[1]||window
    for(let i = 0;i<array.length;i++){
        currentValue = array[i]
        index = i
        callback.call(thisArg,currentValue,index,array)
    }
}
Array.prototype.myReduce = function(callback){
    let accumulator,currentValue,index,array = this
    let initialValue = arguments[1]
    if(initialValue==undefined){
        accumulator = array[0]
    }else{
        accumulator = initialValue
        accumulator = callback(accumulator,array[0],0,array)
    }
    for(let i = 1;i<array.length;i++){
        currentValue = array[i]
        index = i
        accumulator = callback(accumulator,currentValue,index,array)
    }
    return accumulator
}

let testArray2 = [1,2,3,4,5]

testArray2.myForEach((ele,index,self)=>{
    console.log(ele)
})
let sum = testArray2.myReduce((accumulator,currentValue,index)=>{
    console.log(accumulator,index)
    accumulator+=currentValue
    return accumulator
})
console.log(sum)