JS高级编程2-使用高阶函数

高阶函数

高阶函数

高阶函数作为函数式编程众多风格中的一项显著特征,经常被使用。实际上,高阶函数即对函数的进一步抽象。
高阶函数至少满足下列条件之一:接受函数作为输入;输出一个函数。

在函数式语言中,函数不但是一种特殊的对象,还是一种类型,因此函数本身是一个可以传来传去的值。也就是说,某个函数在刚开始执行的时候,总可以送入一个函数的参数。传入的参数本身就是一个函数。当然,这个输入的函数相当于某个函数的另外一个函数。当函数执行完毕之后,又可以返回另外一个新的函数,这个返回函数取决于return fn(){…}。上述过程出现3个不同的函数,分别有不同的角色。要达到这样的应用目的,需要把函数作为一个值来看待。

JavaScript不但是一门灵活的语言,而且是一门精巧的函数式语言。下面看一个函数作为参数的示例。
document.write([2,3,1,4].sort()); //”1,2,3,4”

这是最简单的数组排序语句。实际上Array.prototype.sort()还能够支持一个可选的参数“比较函数”,其形式如sort(fn)。fn是一个函数类型的值,说明这里应用到高阶函数。再如,下面这个对日期类型排序的sort()。

// 声明3个对象,每个对象都有属性id和date 
var a  = new Object(); 
var b  = new Object(); 
var c  = new Object(); 
a.id   = 1; 
b.id   = 2; 
c.id   = 3; 
a.date = new Date(2012,3,12); 
b.date = new Date(2012,1,15); 
c.date = new Date(2012,2,10); 
// 存放在arr数组中 
var arr = [a, b, c]; 
//开始调试,留意id的排列是按1、2、3这样的顺序的 
arr.sort( 
  function (x,y) { 
    return x.date-y.date; 
  } 
); 
//已经对arr排序了,发现元素顺序发生变化,id也发生变化。排序是按照日期进行的

在数组排序的时候就会执行“function (x,y) {return x.date-y.date; }”这个传入的函数。当没有传入任何排序参数时,默认当x大于y时返回1,当x等于y时返回0,当x小于y时返回–1。

除了了解函数作为参数使用外,下面再看看函数返回值作为函数的情况。定义一个wrap函数,该函数的主要用途是产生一个包裹函数。

function wrap(tag) {
    var stag = '<' + tag + '>';
    var etag = '</' + tag.replace(/s.*/, '') + '>';
    return function(x) {
        return stag + x + etag;
    }
}
var B = wrap('B');
document.write(B('粗体字'));
document.write('<br>');
document.write(wrap('B')('粗体字'));

“var B = wrap(‘B’);”这一语句已经决定了这是一个“加粗体”的特别函数,执行该B()函数就会产生 …内容…的效果。若是wrap(‘div’),就会产生…内容…的效果,若是wrap(‘li’),就会产生…内容…的效果,依此类推。wrap(‘B’)返回到变量B的是一个函数。若不使用变量,wrap(‘B’)也是合法的JavaScript语句,只要最后一个括号()前面的是函数类型的值即可。为什么stag + x + etag中的stag/etag没有输入也会在wrap()内部定义?因为warp作用域中就有stag、etag两个变量。如果从理论上描述这一特性,应该属于闭包方面的内容。

实际上,map()函数即为一种高阶函数,在很多的函数式编程语言中均有此函数。map(array, func)的表达式已经表明,将func函数作用于array中的每一个元素,最终返回一个新的array。应该注意的是,map对array和func的实现是没有任何预先的假设的,因此称为“高阶”函数。

function map(array, func) {
    var res = [];
    for(var i = 0, len = array.length; i < len; i++) {
        res.push(func(array[i]));
    }
    return res;
}
var mapped = map([1, 3, 5, 7, 8], function(n) {
    return n = n + 1;
});
print(mapped);  //2,4,6,8,9
var mapped2 = map(["one", "two", "three", "four"], function(item) {
    return "(" + item + ")";
});

print(mapped2);(one), //(two),(three),(four),为数组中的每个字符串加上括号

mapped和mapped2均调用了map,但得到了截然不同的结果。因为map的参数本身已经进行了一次抽象,map函数做的是第二次抽象,所以高阶的“阶”可以理解为抽象的层次。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值