我是靠谱客的博主 贪玩御姐,最近开发中收集的这篇文章主要介绍js高阶函数——Map/ reduce /Fileter/From...,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

每次看到大佬在处理数据的时候,es6789加各种高阶函数一顿操作,3行代码就解决了自己哼哧哼哧下来写了十几行代码才能完成的功能,就在心里暗自流泪,默默发四有一天我也一定要成为大佬,终于。。。这一天要来临了!

正文

一、高阶函数——Map

  1. 首先认识一下map函数是什么?
    MDN官方介绍:map()方法是一个数组的高阶函数,接受一个带有返回值的函数,使得数组的每一个元素都会调用这个指定的方法后形成一个新数组,但不改变原数组。

  2. map函数的描述

    let a = [1, 2, 3, 4]
    let b = a.map(function (value, index, array) {
    return value * 2
    },thisArg)
    console.log(b);//[2, 4, 6, 8]
    

    map函数接收两个参数

    • 必选——callback函数 ,函数内部函数 每个处理元素后的结果,最终组成一个新数组。接收三个参数其中:
      • value(必选):指正在处理的元素
      • index(可选):指正在处理的元素的索引
      • array(可选):指被处理的数组
    • 可选——thisArg:指的是函数内部this的指向。根据下面例子可以看出,如果没有传第二个参数时,map的内部this指向window,传了参数后this指向改变为所传的参数。
     let array = [1,2,3,4]
    let b = array.map(function (value, index, array) {
    console.log(this,1);//Window 
    return value * 2
    })
    let d = array.map(function (value, index, array) {
    console.log(this,2);//[1,2,3,4]
    return value * 2
    },array)
    let f = array.map(function (value, index, array) {
    console.log(this,3); // []
    return value * 2
    },[])
    

    我们接下来再看下一下这个例子

    let a = [1, 2, 3, 4]
    let b = a.map(function (value, index, array) {
    a.push(5)
    console.log(a);//[1, 2, 3, 4, 5,5,5,5]
    return value * 2
    })
    console.log(b);//[2, 4, 6, 8]
    

    这次我在map函数中给原数组添加了新元素,但是最终返回结果却没有跟着变化,那我们如果删除原数组中的元素返回结果还会是之前的吗?

    let a = [1, 2, 3, 4]
    let b = a.map(function (value, index, array) {
    a.shift()
    console.log(a);// [2, 3, 4]---> [3 ,4]
    return value * 2
    })
    console.log(b);//[2, 6, undefined, undefined]
    

    在函数内部循环删除了原数组的首个元素,返回结果发生了改变,综上理解一下这个过程:

    • 在 map 方法执行的过程中:原数组中新增加的元素将不会被 callback 访问到。
    • 若已经存在的元素被改变或删除了,则它们的传递到 callback 的值是 map 方法遍历到它们的那一时刻的值;而被删除的元素将不会被访问到。
    • 使用 map 方法处理数组时,数组元素的范围是在 callback 方法第一次调用之前就已经确定了。

    下面我们就开始结合es6相来处理数据

  3. map函数的应用

    • 格式化数组中的对象
    
    let kvArray =
    [{key: 1, value: 10},
    {key: 2, value: 20},
    {key: 3, value: 30}];
    let newArr = kvArray.map(item => {
    let obj = {}
    obj[item.key] = item.value
    return obj
    })
    // newArr2 是 newArr 的简写形式
    let newArr2 = kvArray.map(item=>({[item.key]:item.value}))
    console.log(newArr); //[Object { 1: 10 }, Object { 2: 20 }, Object { 3: 30 }]
    console.log(newArr2,'00');//[Object { 1: 10 }, Object { 2: 20 }, Object { 3: 30 }] "00"
    
    1. 取数组对象中的某一个特定参数
     let j = kvArray.map(x=>x.value)
    console.log(j) //[10, 20, 30]
    
    1. 格式化字符串
     let newStr = Array.prototype.map.call('new String', x => x + '*')
    console.log(newStr); //["n*", "e*", "w*", " *", "S*", "t*", "r*", "i*", "n*", "g*"]
    //number转字符串
    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    arr.map(String); // ['1', '2', '3', '4', '5', '6', '7', '8', '9']
    
    1. 遍历dom取值
    
    <select id="mapSelect">
    <option value="map1">map1</option>
    <option value="map2" disabled>map2</option>
    <option value="map3" disabled>map3</option>
    </select>
    let select = document.querySelectorAll('option:disabled')
    let option = Array.prototype.map.call(select, x => x.value)
    console.log(option);//["map2", "map3"]
    
    1. 字符串转Number

      通常情况下,map 方法中的 callback 函数只需要接受一个参数,就是正在被遍历的数组元素本身。但这并不意味着 map 只给 callback 传了一个参数。这个思维惯性可能会让我们犯一个很容易犯的错误。

      	let b = ["1", "2", "3"].map(parseInt);
      console.log(b) // [1, NaN, NaN]
      

      通常使用parseInt时,只需要传递一个参数,但实际上,parseInt可以有两个参数.第二个参数是进制数, map方法在调用callback函数时,会给它传递三个参数:当前正在遍历的元素, 元素索引, 原数组本身。 第三个参数parseInt会忽视, 但第二个参数不会,也就是说: parseInt把传过来的索引值当成进制数来使用!从而返回了NaN!

      所以我们可以改造一下该方法:

      function returnInt(element) {
      return parseInt(element, 10);
      }
      ['1', '2', '3'].map(returnInt); // [1, 2, 3]
      // 也可以使用简单的箭头函数,结果同上
      ['1', '2', '3'].map( str => parseInt(str) );
      // 一个更简单的方式:
      ['1', '2', '3'].map(Number); // [1, 2, 3]
      

    好了Map基本学习完了,接下来看一下reduce累加器

二、高阶函数——Reduce 累加器

  1. Reduce函数是什么?
    reduce() 方法接收一个函数作为累加器(accumulator),对数组中的每个元素(从左往右,升序执行)执行这个reducer函数,最后将其计算结果汇总并返回。

  2. reduce 的写法与特征

    let a = [1, 2, 3, 4]
    let b = a.reducer(function (accumulator,value, index, array) {
    return value + accumulator
    },initialValue)
    console.log(b);//10
    

    reduce函数接收两个参数

    • 必选——callback函数,返回累加器的最终计算结果,接收四个参数其中:
      • accumulator(必选):上一次累加计算回调的返回值,首次计算取initialValue得值。
      • value(必选):指正在处理的元素
      • index(可选):指正在处理的元素的索引
      • array(可选):指被处理的数组
    • 可选——initialValue:作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用处理的数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。

    为了更好的理解参数之间的关系,我们来看一个例子:

    	var arr = [1, 2, 3, 4, 5];
    let d = null
    let b = arr.reduce(function (x, y,i) {
    let c = x+y
    console.log('x:'+i,x)
    console.log('y:'+i,y)
    console.log('c:'+i,c)
    return c
    }, d);
    console.log(b, 'b')
    
    1. 当传入参数为null 或 空 或 布尔值False 或数字 0 时,打印的值依次为:
    
    let d = null / fasle / 0
    > "x:0" null / fasle / 0 > "y:0" 1 > "c:0" 1
    > "x:1" 1	> "y:1" 2	> "c:1" 3
    > "x:2" 3	> "y:2" 3	> "c:2" 6
    > "x:3" 6	> "y:3" 4	> "c:3" 10
    > "x:4" 10	> "y:4" 5	> "c:4" 15
    > 15 "b"
    
    1. 当传入参数为 Boolean (TRUE)时,打印值依次为 :
    
    let d = true
    > "x:0" true	> "y:0" 1	> "c:0" 2
    > "x:1" 2	> "y:1" 2	> "c:1" 4
    > "x:2" 4	> "y:2" 3	> "c:2" 7
    > "x:3" 7	> "y:3" 4	> "c:3" 11
    > "x:4" 11	> "y:4" 5	> "c:4" 16
    > 16 "b"
    
    1. 当传入参数为undefined时,打印值依次为 :
    	let d = undefined
    > "x:0" undefined	> "y:0" 1	> "c:0" NaN
    > "x:1" NaN	> "y:1" 2	> "c:1" NaN
    > "x:2" NaN	> "y:2" 3	> "c:2" NaN
    > "x:3" NaN	> "y:3" 4	> "c:3" NaN
    > "x:4" NaN	> "y:4" 5	> "c:4" NaN
    > NaN "b"
    
    1. 当传入参数为非0的number数字时,打印值依次为 :
    	let d = 10
    > "x:0" 10	> "y:0" 1	> "c:0" 11
    > "x:1" 11	> "y:1" 2	> "c:1" 13
    > "x:2" 13	> "y:2" 3	> "c:2" 16
    > "x:3" 16	> "y:3" 4	> "c:3" 20
    > "x:4" 20	> "y:4" 5	> "c:4" 25
    > 25 "b"
    
    1. 当传入参数为字符串时,打印值依次为 :
    	let d = 'aa'
    > "x:0" "aa"	> "y:0" 1	> "c:0" "aa1"
    > "x:1" "aa1"	> "y:1" 2	> "c:1" "aa12"
    > "x:2" "aa12"	> "y:2" 3	> "c:2" "aa123"
    > "x:3" "aa123"	> "y:3" 4	> "c:3" "aa1234"
    > "x:4" "aa1234"	> "y:4" 5	> "c:4" "aa12345"
    > "aa12345" "b"
    
    1. 当传入参数为数组时,打印值依次为:
    	let d = ['a','b']
    > "x:0" Array ["a", "b"]	> "y:0" 1	> "c:0" "a,b1"
    > "x:1" "a,b1"	> "y:1" 2	> "c:1" "a,b12"
    > "x:2" "a,b12"	> "y:2" 3	> "c:2" "a,b123"
    > "x:3" "a,b123"	> "y:3" 4	> "c:3" "a,b1234"
    > "x:4" "a,b1234"	> "y:4" 5	> "c:4" "a,b12345"
    > "a,b12345" "b"
    
    1. 当不传参数时,打印值依次为
    > "x:1" 1	> "y:1" 2	> "c:1" 3
    > "x:2" 3	> "y:2" 3	> "c:2" 6
    > "x:3" 6	> "y:3" 4	> "c:3" 10
    > "x:4" 10
    > "y:4" 5	> "c:4" 15
    > 15 "b"
    

    通过以上几个例子,我们可以看出来,在可选值 initialValue 传递参数的时候,可以得出几个特征:

    • 不传递参数(例7),x 取得数组的第一项,y取得数组第二项,直接从索引为1开始计算。
    • 传递参数,x 取得传入参数d的值,y取数组的第一项,从索引为0开始计算,累加结果为x和y之和。
    • reduce返回的值b 是最后一次回调返回值(15)。
    • 当传入布尔值为true时(例2), "x:0" true "y:0" 1 "c:0" 2 ,在js运算中,会把 true 隐式转换为1, false隐身转换为0,所以累加器 c 的输出结果为 2。最终结果为16。

下面我们看一下reduce日常的应用

  1. reduce 的应用

    1. 计算数组或对象里值的和或各种运算
    var initialValue = 0;
    var sum = [{x: 1}, {x:2}, {x:3}].reduce(function (accumulator, currentValue) {
    return accumulator + currentValue.x;
    },initialValue)
    var sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) {
    return accumulator + currentValue;
    }, initialValue);
    console.log(sum) //
    6
    
    1. 将二维数组转化为一维
    var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
    function(a, b) {
    return a.concat(b);
    }, []);
    // flattened
    [0, 1, 2, 3, 4, 5]
    
    1. 将多维数组转化为以为数组
    let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
    const newArr = function(arr){
    return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
    }
    console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]
    
    1. 数组排序去重
    
    let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
    let result = arr.sort().reduce((x,y)=>{
    if(x.length == 0 || x[x.length-1] !== y)
    x.push(y)
    return x
    },[])
    console.log(result);//[1, 2, 3, 4, 5]
    
    1. 计算字符串或者数组内部元素出现的次数
    	字符串
    var arrString = 'abcaabc';
    let result = arrString.split('').reduce((x, cur)=> {
    x[cur] ? x[cur]++ : x[cur] = 1
    return x;
    }, {})
    console.log(result);//{a: 3, b: 2, c: 2}
    数组
    var names
    = ['Alice', 'Bob', 'cc', 'cc', 'Alice'];;
    let result = names.reduce((x, cur)=> {
    x[cur] ? x[cur]++ : x[cur] = 1
    return x;
    }, {})
    console.log(result);//{Alice: 2, Bob: 1, cc: 2}
    
    1. 按顺序执行promise
    
    function p1(a) {
    return new Promise((resolve, reject) => {
    resolve(a * 5);
    });
    }
    function p2(a) {
    return new Promise((resolve, reject) => {
    resolve(a * 2);
    });
    }
    function f3(a) {
    return a * 3;
    }
    function p4(a) {
    return new Promise((resolve, reject) => resolve(a * 4));
    }
    let pall = [p1, p2, f3, p4]
    let e = pall.reduce((x, y) => {
    return x.then(y)
    }, Promise.resolve(10))
    //输入10 ,经过p1变为50,p2变为100,f3变为300,p4变为1200
    e.then(console.log)//1200
    

    以上 关于reduce的学习就到这里了,下面学习一下Fileter

三、高阶函数——Fileter 过滤

  1. Fileter 函数是什么?
    fileter ()方法是一个数组的高阶函数,接受一个带有返回值的函数,使得数组的每一个元素都会调用这个指定的判断条件后,满足条件的元素的组成形成一个新数组,不改变原数组。

  2. Fileter 的特征?
    fileter函数和map函数的特征基本一致!很像很像,同样接收两个参数:

    • 必选——callback函数 ,函数内部函数 每个处理元素后的结果,最终组成一个新数组。接收三个参数其中:
      • value(必选):指正在处理的元素
      • index(可选):指正在处理的元素的索引
      • array(可选):指被处理的数组
    • 可选——thisArg:指的是函数内部this的指向。根据下面例子可以看出,如果没有传第二个参数时,map的内部this指向window,传了参数后this指向改变为所传的参数。

    具体就不举例说明了,可参照map的例子自己验证一下,下面直接看如何应用:

  3. Fileter 函数的应用

    • 筛选数组中满足条件的元素
     let filter = [2,322.4,,56,345,24,566,'123'].filter(item=>item>100)
    console.log(filter);// [322.4, 345, 566, "123"]
    
     let filter = ['aads','bb','ccaa','ddbba'].filter(item=>item.includes('aa'))
    console.log(filter);// ["aads", "ccaa"]
    
    1. 选出数组对象中满足条件的对象
    
    let filter = [{x:1},{x:34},{x:9}].filter(item=>item.x <10)
    console.log(filter);//Array [{ x: 1 },{ x: 9 }]
    

    3.数组排序去重

    
    let arr1 = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
    let result = arr1.sort().filter((x, y,self) => x !== self[y-1] )
    console.log(result); //[1, 2, 3, 4, 5]
    

四、Array.from()

  1. from函数是什么?
    Array.from()可以将类数组和可迭代(Iterator)的对象转化为真实数组,但不改变初始值。

    1. 部署了Iterator接口的对象,比如:Set,Map,Array,String。
    2. 类数组对象,就是一个对象必须有length属性,没有length,转出来的就是空数组。
  2. from 的描述?
    from 方法 接收三个参数:

    • 必选——arrayLike:想要转换成数组的伪数组对象或可迭代对象。
    • 可选——map函数:每个项目调用该函数将返回的值将插入到新数组中。
    • 可选——thisArg:指的是map函数内部this的指向。
    	const someNumbers = { '0': 10, '1': 15, length: 2 }
    //转化类数组
    let arr = Array.from(someNumbers)
    //使用es6箭头函数最简写
    let arr1 = Array.from(someNumbers, value => value * 2)
    //es6简写
    let arr2 = Array.from(someNumbers).map((value) => {
    return value * 2
    })
    //方便理解版
    let arr3 = Array.from(someNumbers, function (value) {
    return value * 2
    })
    console.log(arr) // =>[10, 15]
    console.log(arr1); // => [20, 30]
    console.log(arr2); // => [20, 30]
    console.log(arr3); // => [20, 30]
    
  3. from函数的应用

    1. 将类数组转化为数组,比如上述的例子或者填充数据
    let arr =
    Array.from({ length: 2 }, (x,i) => 'jack'+i)
    console.log(arr);//["jack0", "jack1"]
    
    1. 生成数字范围
    
    function range(end) {
    return Array.from({
    length: end
    }, (x, index) => index);
    }
    console.log( range(4));; // => [0, 1, 2, 3]
    
    1. 填充数组中布尔值为false的项如:undefined,null,0,fasle,空
    let arr = [1,0,,,2,null,,3,false,4,'a',5,,]
    let arr1 =
    Array.from(arr, x => x||'无')
    console.log(arr);//[1, 0, undefined, undefined, 2, null, undefined, 3, false, 4, "a", 5, undefined]
    
    console.log(arr1);//[1, "无", "无", "无", 2, "无", "无", 3, "无", 4, "a", 5, "无"]
    
    1. 格式化字符串
    
    let newStr = Array.from('new String', x => x + '*')
    console.log(newStr); //["n*", "e*", "w*", " *", "S*", "t*", "r*", "i*", "n*", "g*"]
    //number转字符串
    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    let arr2 = Array.from(arr,x=>x.toString())
    console.log(arr2);//["1", "2", "3", "4", "5", "6", "7", "8", "9"]
    
    1. 数组排序去重
    	let arr1 = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4].sort();
    let result = Array.from(new Set (arr1))
    console.log(result); //[1, 2, 3, 4, 5]
    

    由于from的第二个函数可以调用map函数,所以map可以做到的应用from都可以做到,并返回新数组。

结语

以上就是几个常用但是不太好用理解的高阶函数的学习过程,map和filter都是在处理数组方面很优秀,但是map在数据量很大的情况下性能方面次于foreach和for循环,所以根据情况使用,reduce累加的过程理解可能比较困难,多联系几个demo就可以了!!加油!!对了这几个都不兼容ie8急以下。。。放弃ie8了,我才不管他呢,哼

如果本文对你有帮助的话,请不要忘记给我点赞打call哦~o( ̄▽ ̄)do
有其他问题留言 over~

最后

以上就是贪玩御姐为你收集整理的js高阶函数——Map/ reduce /Fileter/From...的全部内容,希望文章能够帮你解决js高阶函数——Map/ reduce /Fileter/From...所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部