js高阶函数

一、高阶函数(Higher-order function)

高阶函数其实并不复杂,对于学习javaScript的小伙伴,可能已经使用过却不自知。了解高阶函数之前可以先了解函数式编程一等函数两个概念。

1. 函数式编程(Functional Programming, FP)

函数式编程是一种编程方式,函数编程支持函数作为第一类对象,有时称为闭包或者仿函数(functor)对象。实质上,闭包是起函数的作用并可以像对象一样操作的对象。与此类似,FP 语言支持高阶函数。高阶函数可以用另一个函数(间接地,用一个表达式) 作为其输入参数,在某些情况下,它甚至返回一个函数作为其输出参数。这两种结构结合在一起使得可以用优雅的方式进行模块化编程,这是使用 FP 的最大好处。简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。它属于"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用。JavaScript,Haskell,Clojure,Scala和Erlang是实现函数式编程的一些语言。

2. 一等函数(first-Class Function)

一等函数可以理解为函数是“第一等公民(first class)”,所谓"第一等公民"(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。在javaScript或者任何其他函数式编程语言中,函数是对象,在javaScript中,函数是一种特殊类型的对象—Function对象。javaScript将函数视为一等公民(first class),因为函数与其他数据类型(比如对象、字符串或者数字等)一样,对于可以使用其他数据类型执行的操作,函数都可以执行,因此javaScript中的函数可以被称之为一等函数(first-Class Function)。

3. 高阶函数(Higher-order function)

在函数式编程和一等函数概念的理解之上,简单的说,高阶函数就是对其他函数进行操作的函数:函数可以作为参数被传递,也可以作为返回值被输出。javaScript的函数其实都指向某个变量,变量可以指向函数,函数的参数可以接收变量,因此一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。编写高阶函数,就是让函数的参数能够接收别的函数。高阶函数至少满足下列条件之一:(1)函数可以作为参数被传递(如回调函数等);(2)函数可以作为返回值输出。

二、高阶函数应用场景

1. 高阶函数实现AOP

AOP(面向切面编程, Aspect Oriented Programming),其主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些无关模块通常包括日志统计,安全控制,异常处理等,然后再将这些支撑模块“动态织入”到另一个函数中去,js中可以很方便的利用高阶函数实现AOP编程。

2. 函数柯里化(currying)

函数柯里化又称为部分求值,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。例1例2例3

3. 函数节流(throttle)

函数节流,即函数预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。针对一些被频繁调用的函数,如onresize,mousemove等,它们共同的特征是函数被触发的频率太高,事实上可能并不需要以这么高的频率调用,因此可以使用函数节流为此类函数指定触发的间隔。例:

// 函数节流
var canRun = true;
document.getElementById("throttle").onscroll = function(){
    if(!canRun){
        // 判断是否已空闲,如果在执行中,则直接return
        return;
    }

    canRun = false;
    setTimeout(function(){
        console.log("函数节流");
        canRun = true;
    }, 300);
};

函数节流的原理是:延迟当前函数的执行,如果该次延迟还没有完成,那么忽略接下来该函数的请求。也就是说会忽略掉很多函数请求。除函数节流外,还有函数防抖(debounce):函数调用n秒后才会执行,如果函数在n秒内被调用的话则函数不执行,重新计算执行时间。例:

 // 函数防抖
var timer = false;
document.getElementById("debounce").onscroll = function(){
    clearTimeout(timer); // 清除未执行的代码,重置回初始化状态

    timer = setTimeout(function(){
        console.log("函数防抖");
    }, 300);
};  

需要注意的一点:函数的节流和函数防抖都是通过减少实际逻辑处理过程的执行来提高事件处理函数运行性能的手段,并没有实质上减少事件的触发次数

4. 分时函数

分时函数和函数节流的问题不一样,函数节流针对的事件不是用户主动调用的,而分时函数处理的问题是用户主动调用的。一个例子是创建WebQQ的QQ好友列表。列表中通常会有成百上千个好友,如果一个好友用一个节点来表示,当我们在页面中渲染这个列表的时候,可能要一次性往页面中创建成百上千个节点。在短时间内往页面中大量添加DOM节点显然也会让浏览器吃不消,我们看到的结果往往就是浏览器的卡顿甚至假死。

这个问题的解决方案之一是下面的timeChunk函数,timeChunk 函数让创建节点的工作分批进行,比如把1秒钟创建1000个节点,改为每隔200毫秒创建8个节点。timeChunk函数接受3个参数,第1个参数是创建节点时需要用到的数据,第2个参数是封装了创建节点逻辑的函数,第3个参数表示每一批创建的节点数量。代码如下:

var timeChunk = function( ary, fn, count ){

    var obj,
        t;

    var len = ary.length;

    var start = function(){
        for ( var i = 0; i < Math.min( count || 1, ary.length ); i++ ){
            var obj = ary.shift();
            fn( obj );
        }
     };

     return function(){
        t = setInterval(function(){
          if ( ary.length === 0 ){  // 如果全部节点都已经被创建好
              return clearInterval( t );
          }
          start();
        }, 200 );    // 分批执行的时间间隔,也可以用参数的形式传入

    };

};

三、高阶函数例子

map()、reduce()、filter()

 

参考引用:

  1. https://blog.csdn.net/qq_22844483/article/details/83753048
  2. https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434499355829ead974e550644e2ebd9fd8bb1b0dd721000
  3. https://www.cnblogs.com/bobodeboke/p/5594647.html
  4. http://www.cnblogs.com/goloving/p/8361705.html
  5. https://baike.baidu.com/item/%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B/4035031?fr=aladdin
  6. https://www.cnblogs.com/caizhenbo/p/6378202.html
  7. https://blog.csdn.net/sinat_25127047/article/details/70741597
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值