【javascript】JavaScript高阶函数介绍

★本文引自:廖雪峰的官方网站
- 高阶函数:即一个函数可以接收另一个函数作为参数,这种函数就称之为高阶函数。

function add(x,y,fn) {
    return fn(x) + fn(y);
}
console.info(add(-5,6,Math.abs));

当我们调用add(-5,6,Math.abs)时,结果会输出11
编写高阶函数,就是让函数的参数能够接收别的函数。

案例一:高阶函数 - 数组Map遍历

比如我们有一个f(x) = x * x;要把这个函数作用在一个数组[1,2,3,4,5,6,7,8,9]上,就可以用map实现如下:

function pow(x) {
    return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.info(arr.map(pow));     //输出 -> [1, 4, 9, 16, 25, 36, 49, 64, 81]

map()传入的参数是pow,即函数对象本身。
你可能会想,不需要map(),写一个循环,也可以计算结果:

var fn = function(x) {
    return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [];
for(var i=0;i < arr.length; i++) {
    result.push(fn(arr[i]));
}
console.info(result);       //[1, 4, 9, 16, 25, 36, 49, 64, 81]

的确可以,但是,从上面的循环代码,我们无法一眼看明白把f(x)作用在Array的每个元素并把结果生成一个新的Array
所以,map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x * x,还可以计算任意复杂的函数,比如把Array的所有数字转为字符串:

//只需要一行代码
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.info(arr.map(String));
案例二:高阶函数 - 数组reduce

再看reduce的用法。Array的reduce()把一个函数作用在这个Array[x1, x2, x3...]上,这个函数必须接受两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果就是:

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

比方说对一个Array求和,就可以用reduce实现:

var arr = [1, 3, 5, 7, 9];
var sum = arr.reduce(function(x, y){
    return x + y;
});
console.info(sum);
案例三:高阶函数 — 数组filter

filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。
map()类似,Arrayfilter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
例如,在一个Array中,删除掉偶数,只是留奇数,可以这么写:

var arr = [1, 2, 4, 6, 9, 10, 15];
var r = arr.filter(function(x){
    return x % 2 !==0;
});
console.info(r);        //输出 -> [1, 9, 15]
  • 把一个Array中的空字符串删除掉,可以这么写:
var arr = ['A','','B',null,undefined,'C','  '];
var r = arr.filter(function(s){
    return s && s.trim();
});
console.info(r);            //输出 -> ["A", "B", "C"]
  • 我们利用filter,可以巧妙地去除Array的重复元素,代码实现如下:
var r,arr = ['apple','strawberry','banana','pear','apple','orange','orange','strawberry'];
console.info(arr.indexOf('orange'));    //输出 -> 5,从左往右数第一个元素下标
var i = 0;
r = arr.filter(function(element, index, self){
    console.info("第" + i +"个元素:" + (self.indexOf(element) === index));
    //依次输出:
        //第0个元素:true
        //第1个元素:true
        //第2个元素:true
        //第3个元素:true
        //第4个元素:false
        //第5个元素:true
        //第6个元素:false
        //第7个元素:false
    i++;
    return self.indexOf(element) === index;
});
console.info(r);        //输出 -> ["apple", "strawberry", "banana", "pear", "orange"]

上面代码实现去除元素依靠的是indexOf总是返回第一个元素的位置,后续的重复元素位置与indexOf返回的位置不相等,因此被filter滤掉。

高阶函数 — sort排序算法

排序也是在程序中经常用到的算法。无论使冒泡排序还是快速排序,排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果是字符串或者两个对象呢?直接比较数学上的大小是没意义的,因此,比较过程必须通过函数抽象出来。通常规定,对于两个元素xy,如果认为x<y,返回-1,如果认为x==y,返回0,如果x>y,则返回1,这样,排序算法就不用关心具体的比较过程,而是根据比较结果直接排序。

JavaScript的Arraysort()方法就是用于排序的,但是排序结果可能大吃一惊:

/*看上去正常的结果: */
console.info(['Google', 'Apple', 'Microsoft'].sort());  //["Apple", "Google", "Microsoft"]
/*apple排在了最后:*/
console.info(['Google', 'apple', 'Microsoft'].sort());  //["Google", "Microsoft", "apple"]
/*无法理解的结果:*/
console.info([10, 20, 1, 2].sort());    //[1, 10, 2, 20]

第二个排序把apple排在了最后,是因为字符串根据ACSII码进行排序,而小写字母a的ASCII码在大写字母之后。
第三个排序结果是什么鬼?简单的数字排序都能错?
这是因为Arraysort()方法默认把所有元素先转换为String再排序,结果10排在了2的前面,因为字符1比字符2的ASCII小。
如果不知道sort()方法的默认排序规则,直接对数字排序,绝对栽进坑里!
幸运的是,sort()方法也是一个高阶函数,它还可以接收一个比较函数来实现自定义的排序。
要按数字大小排序,我们可以这么写:

var arr = [10, 20, 1, 2];
var result = arr.sort(function(x ,y){
    console.info(x ,y, arr);            //重做往右比较,然后
    if(x < y) {
        return -1;                      //排序是两个比较之后的值-1,1,0来决定比较元素的位置是向左、向右或者保持不变
    }
    if(x > y) {
        return 1;
    }
    return 0;
});
console.info(arr);                      //[1, 2, 10, 20]
console.info(arr === result);           //返回为true,表明arr和result是同一对象,上面排序对原`Array`进行了修改
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值