手写every、some、find、findIndex、forEach、map、filter、reduce

every

首先,我们要了解我们要手写的整个函数它的功能

every:依次遍历数组中的每项,当碰到一项不满足条件,则返回false,只有当全部符合条件时则返回true

array.every(function(currentValue,index,arr), thisValue)

在这里插入图片描述

var arr = [101, 12, 32, 2, 3, 44, 120, 3, 5];

// every 表示每一项都必须通过才会返回true
// every对每一个元素执行一个callback
// 直到它找到一个使 callback 返回 false的元素, 就返回false
// 直到遍历完成也没有返回false的话,就返回true
console.log(arr.every(i => { return i > 50 }))

// every 手写
Array.prototype.myevery = function (fn) {
    if (typeof (fn) != 'function') {
        throw new TypeError(`error ${fn} no a function`)
    }
    for (let i = 0; i < this.length; i++) {
        // 对arr中项依次执行if语句
        // 当碰到一项不满足>50则退出整个函数,不再执行执行下面的项
        if (!fn(this[i])) {
            return false;
        }
    }
    return true
}
let my = arr.myevery(item => { return item > 50; })
console.log(my)

// function test() {
//     for (let i = 0; i < 10; i++) {
//         console.log(i)
//         // 说明return false可以退出函数,不继续执行
//         if (arr[i] < 50) {
//             return false
//         }
//     }
//     return 90
// }
// test()
// // console.log(test())

some

some:依次遍历数组的每一项,当遇到一项满足条件便返回true,不再继续后面的遍历,跟every作用正好相反

array.some(function(currentValue,index,arr),thisValue)

var arr = [1, 12, 32, 2, 3, 44, 120, 3, 5];
// 只要有一项满足就返回true,不再继续执行
// console.log(arr.some(item => { return item > 50 }))//true

//手写some
// fn是代表数组每一项要执行的函数,必须使用function不能使用箭头函数
Array.prototype.mysome = function (fn) {
    if (typeof fn != 'function') {
        console.log(`${fn} is not a function`)
        return false
    }
    // this指向调用mysome函数的对象,即是arr
    for (let i = 0; i < this.length; i++) {
        if (fn(this[i])) {
            // 只要有一项满足条件则跳出函数,不继续执行
            return true
        }
    }
    //当所有的都不满足条件时通过下面这个返回false,并跳出函数
    return false
}
let my = arr.mysome(item => { return item > 50 });
console.log(my)//true

find

find的作用和some类似,都是当遇到一项满足条件便返回true,不再继续后面的遍历区别:find是返回满足条件的第一个值,some是当遇到满足条件的第一项时返回true

array.find(function(currentValue, index, arr),thisValue)

// 由于和some方法并没有区别,只是返回值有区别,在此不详细贴出代码
var arr = [1, 12, 32, 2, 3,120, 44, 3, 5];
// 只要有一项满足就返回该值,不再继续执行,否则返回undefind
console.log(arr.find(item => { return item > 50 }))//120

// 手写find
// 只要有一项满足条件则跳出函数,不继续执行
   return this[i]
//当所有的都不满足条件时通过下面这个返回undefined,并跳出函数
   return undefined

findIndex

findIndex是返回满足条件的第一个值的索引,find和findIndex和some方法类似,区别在于返回值不同。
find和findIndex在全部不满足条件时都返回undefined

array.findIndex(function(currentValue, index, arr), thisValue)

// 由于和find方法并没有区别,只是返回值有区别,在此不详细贴出代码
var arr = [1, 12, 32, 2, 3,120, 44, 3, 5];
// 只要有一项满足就返回该值,不再继续执行,否则返回undefind
console.log(arr.findIndex(item => { return item > 50 }))//5

// 手写findIndex
// 只要有一项满足条件则跳出函数,不继续执行
   return i
//当所有的都不满足条件时通过下面这个返回undefined,并跳出函数
   return undefined

includes

includes和findIndex这两个都可以用来查找数组中是否有某个元素,只是返回值有区别

includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false。

在这里插入图片描述

在这里插入代码片

forEach

forEach 遍历数组全部元素,利用回调函数对数组进行操作
自动遍历数组数组元素个数次,且无法break,return 中途跳出循环,除非抛出异常
注意: forEach() 对于空数组是不会执行回调函数的。

// 对象数组
var arr = [{ name: 'kk', age: 90 }];
//forEach返回值是undefined, foreach不能通过return返回指定的返回值
console.log(arr.forEach(item => { item.age *= 2 }));//undefined
console.log(arr)//[ { name: 'kk', age: 92 } ]

// 普通数组
var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
console.log(arr.forEach(item => { item *= 2 }));//undefined
// 数组无变化
console.log(arr)//[ 1, 12, 32, 2, 3, 120, 44, 3, 5 ]

为什么forEach对普通数组不产生作用呢?
主要在于数组里面每一项是引用数据类型还是基本数据类型

看完这篇链接文章,相信你一定会恍然大悟

你还在以为forEach真的能改变原数组吗?你悟了吗?

forEach有两个参数
在这里插入图片描述

array.forEach(function(currentValue, index, arr), thisValue)

第二个参数thisValue可以设置回调函数中this的指向
JS forEach()第二个参数

forEach每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)

// forEach回调函数会跳过数组空元素
var obj = {}, count = 0;
function logArray(value, index, array) {
    count++;
    obj[count] = value;
}
[1, 2, , 4].forEach(logArray);
console.log(obj); // {1: 1, 2: 2, 3: 4}
console.log(count) // 3

var arr = [101, 12, 32, 2, 3, 44, 120, 3, 5];
var arr2 = [1,2,3,4,5,6];
var arr1 = {name:'kkk',age:50}
// 改变this的指向
arr.forEach(function (item) {console.log(this)},arr1) 
//{ name: 'kkk', age: 50 }*arr.length

// 注意在箭头函数中引用this实际上是调用的是定义时的上一层作用域的this为window。
// js作用域:全局作用域、函数作用域、块级作用域(通过let,const声明的)
arr.forEach(item =>{console.log(this === window)}) //true*arr.length
arr.forEach(item => {console.log(this === window)},arr1) //true*arr.length
arr.forEach(item => {console.log(this === window)},this) //true*arr.length

了解了forEach的功能之后,我们就可以上手自己写一个forEach函数了

var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
var arr2 = [1, 2, 3, 4]
// arr.forEach(function (item, index, arr) {
//     console.log(item, index, this)
// }, arr2)
// 结果太长了,你们可以自己打印看看结果

Array.prototype.myforEach=function(fn,thisArg){
    // this代表调用这个函数的数组
    var _this = this
    // 判断调用myforEach的对象是不是一个数组
    if(!Array.isArray(this)){
        console.log('not a array')
    }
    // 判断传入的是不是函数
     if (typeof fn != 'function') {
        console.log(`${fn} is not a function`)
        return false
    }
    // 有传入第二个参数,改变fn的this指向
    if(arguments.length > 1){
        _this = thisArg;
    }  
    // 对数组每一项执行该函数
    for(let index = 0; index < this.length; index++){
        fn.call(_this,this[index],index,this)
    }
}

arr.myforEach(function(item,index,arr) {
    console.log(item, index, this === window)
},arr2)

map

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值
array.map(function(value, index, array))

var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
var arr2 = [1, 2, 3, 4]
var arr3 = arr.map(function (item, index, arr) {
    return item+index
})
console.log(arr3)

Array.prototype.myMap=function(fn){
    // 判断调用myforEach的对象是不是一个数组
    if(!Array.isArray(this)){
        console.log('not a array')
    }
    // 判断传入的是不是函数
     if (typeof fn != 'function') {
        console.log(`${fn} is not a function`)
        return false
    }
    // 对数组每一项执行该函数
    let resArrary = []
    for(let index = 0; index < this.length; index++){
        resArrary.push(fn(this[index], index, this))
    }
    return resArrary
}

var arr3 = arr.myMap(function(item,index,arr) {
    return index+item
})
console.log(arr3)

filter

返回满足条件的每一项到新数组

var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
var arr2 = [1, 2, 3, 4]
var arr3 = arr.filter(function (item, index, arr) {
    return item+index < 50
})
console.log(arr3)//[ 1, 12, 32, 2, 3, 3, 5 ]

Array.prototype.myFilter=function(fn){
    // 判断调用myforEach的对象是不是一个数组
    if(!Array.isArray(this)){
        console.log('not a array')
    }
    // 判断传入的是不是函数
     if (typeof fn != 'function') {
        console.log(`${fn} is not a function`)
        return false
    }
    // 对数组每一项执行该函数
    let resArrary = []
    for(let index = 0; index < this.length; index++){
        let a = fn(this[index], index, this)
        if(a){
            resArrary.push(this[index])
        }
    }
    return resArrary
}

var arr3 = arr.myFilter(function(item,index,arr) {
    return item+index < 50
})
console.log(arr3)//[ 1, 12, 32, 2, 3, 3, 5 ]

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素。

array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
在这里插入图片描述
total最初初始值默认是数组第一个元素,当有initValue时为initValue
高级技巧请点击下方大佬文章
reduce()方法详解及高级技巧

var arr = [1, 12, 32, 2, 3, 120, 44, 3, 5];
var arr2 = [1, 2, 3, 4]
var arr3 = arr.reduce((total, item, index, arr)=>{
    return item+total
},0)
console.log(arr3)//222

Array.prototype.myReduce=function(fn,initValue){
    // 判断调用myforEach的对象是不是一个数组
    if(!Array.isArray(this)){
        console.log('not a array')
    }
    // 判断传入的是不是函数
     if (typeof fn != 'function') {
        console.log(`${fn} is not a function`)
        return false
    }
    var value = this[0];
    // 对数组每一项执行该函数
    // 有传入第二个参数
    if(arguments.length > 1){
        for(let index = 0; index < this.length; index++){
            initValue = fn.call(this, initValue, this[index], index, this) 
        }
     } 
    else{
            for(let index = 1; index < this.length; index++){
            value = fn.call(this, value, this[index], index, this)
            initValue = value;
            }
        }
    return initValue
}

function test(total,item,index,arr) {
   return total+item
}
var arr3 = arr.myReduce(test,0)
console.log(arr3)//222

// 小注意:
// var arr4 = []
// console.log(arr4.reduce(test,0)) //0
// console.log(arr4.reduce(test)) //TypeError: Reduce of empty array with no initial value

我们平时用到这些函数也需要注意一些小细节:
易错点
以下说不会改变原始数组是指:当数组中元素是值类型,绝对不会改变数组;如果是引用类型,则可以改变数组

  1. every、 some、find、findIndex、forEach、map、filter、reduce不会改变原始数组
  2. map、filter会返回新数组。map返回表达式执行的结果的数组项数组。filter是返回满足表达式的数组项数组
  3. foreach不能通过return返回指定的返回值。
  4. every、some 、filter 、map不会对空数组进行检测。
  5. find 、findIndex、reduce、forEach对于空数组是不会执行回调函数的。forEach、every、some、map、filter、reduce会跳过空元素。find、findIndex不跳过空元素。

拓展:数组常见方法到底有哪些可以改变原数组

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值