Javascript:是你的高阶函数

简介:

 在通常的编程语言中,函数的参数只能是基本类型或者对象引用,返回值也只是基本数据类型或对象引用。但在Javascript中函数作为一等公民,既可以当做参数传递,也可以被当做返回值返回。所谓高阶函数就是可以把函数作为参数,或者是将函数作为返回值的函数。这两种情形在实际开发中有很多应用场景,本文是我在工作学习中遇到的几种应用场景的总结。

  回调函数

  代码复用是衡量一个应用程序的重要标准之一。通过将变化的业务逻辑抽离封装在回调函数中能够有效的提高代码复用率。比如ES5中为数组增加的forEach方法,遍历数组,对每个元素调用同一个函数。


array = {};
array.forEach = function(arr, fn){
    for (var i = 0, len = arr.length; i < len; i++) {
        fn(arr[i], i, arr);
    }
}

 通过回调函数将业务的重点聚焦在回调函数中,而不必每次都要重复编写遍历代码。

  

  偏函数

  作为将函数当做返回值输出的典型应用就是偏函数。所谓偏函数是指创建一个调用另外一个部分——参数或变量已经预置的函数——的函数的用法。反正看着定义我是没理解这东东干嘛的。咱们还是先看例子吧,偏函数最典型的例子就是类型判断。

  Javascript对象都拥有三个属性:原型属性、类属性、可扩展性。(不知道的同学要回去翻犀牛书哦,page:138)类属性是一个字符串,Javascript中并未直接提供,但我们可以利用Object.prototype.toString来间接得到。该函数总是返回如下形式:


[object Class]

因此我们可以编写一系列isType函数。代码如下:


isString = function(obj){
    return Object.prototype.toString.call(obj) === "[object String]";
}
isNumber = function(obj){
    return Object.prototype.toString.call(obj) === "[object Number]";
}
isArray = function(obj){
    return Object.prototype.toString.call(obj) === "[object Array]";
}

这几个函数中大部分代码是重复的,这时高阶函数便华丽丽的登场了:


isType = function(type) {
    return function(obj) {
        return Object.prototype.toString.call(obj) === "[object " + type + "]";
    }
}

isString = isType('String');
isNumber = isType('Number');
isArray = isType('Array');

  所以通过指定部分参数来返回一个新的定制函数的形式就是偏函数。

 

  currying(柯里化)

  currying又称部分求值。一个currying的函数首先会接受一些参数,接受这些参数之后,函数并不会立即求值,而是继续返回另一个函数,刚才传入的参数在函数形成的闭包中被保存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值。


var currying = function(fn) {
    var args = [];
    
    return function() {
        if (arguments.length === 0) {
            return fn.applay(this, args);
        } else {
            args = args.concat(arguments);
            return arguments.callee;
        }
    }
}

假设我们以计算一个月每天花销为例:


var currying = function(fn) {
debugger;
    var args = [];
    
    return function() {
        if (arguments.length === 0) {
            return fn.apply(this, args);
        } else {
            Array.prototype.push.apply(args, arguments);
            return arguments.callee;
        }
    }
}

cost = function(){
    var sum = 0;
    for (var i = 0, len = arguments.length; i < len; i++) {
        sum += arguments[i];
    }
    
    return sum;
}
var cost = currying(cost);

cost(100);
cost(200);
alert(cost())


 事件节流

  在某些场景下,某些事件可能会被重复的触发,但事件处理函数并不需要每次都执行。比如在window.resize事件中进行复杂的逻辑计算,如果用户频繁的改变浏览器大小,复杂计算会对性能造成严重影响;有时这些逻辑计算并不需要每次rezise时都触发,只需要计算有限的几次便可以。这时我们需要根据时间段来忽略一些事件请求。请看以下节流函数:


function throttle(fn, interval) {
      var doing = false;

      return function() {
        if (doing) {
          return;
        }
        doing = true;
        fn.apply(this, arguments);
        setTimeout(function() {
          doing = false;
        }, interval);
      }
    }
    
    window.onresize = throttle(function(){
        console.log('execute');
    }, 500);

 通过控制函数执行时间,可以在函数执行次数与功能需求之间达到完美平衡。另一个事件是mousemove。如果我们给一个dom元素绑定该事件,鼠标在改元素上移动时,该事件便会重复触发。

 

  事件结束

  对于某些可以频繁触发的事件,有时候我们希望在事件结束后进行一系列操作。这时我们可以利用高阶函数做如下处理:


function debounce(fn, interval) {
    var timer = null;

  function delay() {
    var target = this;
    var args = arguments;
    return setTimeout(function(){
      fn.apply(target, args);
    }, interval);
  }

  return function() {
    if (timer) {
      clearTimeout(timer);
    }

    timer = delay.apply(this, arguments);
  }
};
window.onresize = throttle(function(){
    console.log('resize end');
}, 500);

  如果在这一过程中事件被触发则清除上一次事件句柄,重新绑定执行时间。

  

  参考资料:

  《深入浅出node

  《Javascript设计模式与开发实践》




目录
相关文章
|
前端开发 JavaScript
前端基础 - JavaScript高级应用(高阶函数)
前端基础 - JavaScript高级应用(高阶函数)
58 0
|
存储 JavaScript 前端开发
js数组高阶函数——includes()方法
js数组高阶函数——includes()方法
326 0
|
2月前
|
JSON JavaScript 前端开发
JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级
JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级
|
1月前
|
前端开发 JavaScript 索引
JavaScript 数组常用高阶函数总结,包括插入,删除,更新,反转,排序等,如map、splice等
JavaScript数组的常用高阶函数,包括遍历、插入、删除、更新、反转和排序等操作,如map、splice、push、pop、reverse等。
18 0
|
5月前
|
JavaScript 前端开发 测试技术
JavaScript进阶-高阶函数与柯里化
【6月更文挑战第18天】在JavaScript中,高阶函数和柯里化是函数式编程的核心。高阶函数接收或返回函数,常用于数组操作和事件处理。柯里化将多参数函数转化为单参数的逐次求值过程,用于参数预绑定和函数组合。两者能简化逻辑、提高复用性,但也需注意易错点,如混淆参数、过度柯里化,应适度使用并配合测试保证正确性。通过实践和使用工具,如lodash的`_.curry`,能更好地利用这些技术。
49 5
|
6月前
|
JavaScript 前端开发 测试技术
JavaScript中的函数式编程:纯函数与高阶函数的概念解析
【4月更文挑战第22天】了解JavaScript中的函数式编程,关键在于纯函数和高阶函数。纯函数有确定输出和无副作用,利于预测、测试和维护。例如,`add(a, b)`函数即为纯函数。高阶函数接受或返回函数,用于抽象、复用和组合,如`map`、`filter`。函数式编程能提升代码可读性、可维护性和测试性,帮助构建高效应用。
|
6月前
|
前端开发 JavaScript 容器
早期 JavaScript 中的高阶函数与模块化实现
早期 JavaScript 中的高阶函数与模块化实现
|
6月前
|
JavaScript 前端开发
JavaScript中高阶函数与闭包的实际应用
【4月更文挑战第22天】JavaScript中的高阶函数和闭包是强大的工具,常用于抽象、复用和构建组合逻辑。高阶函数如回调、数组方法和函数组合能提高代码灵活性。闭包则用于封装私有变量、创建函数工厂和在异步编程中保留上下文。两者结合使用,如`createAccumulator`函数,能创建更灵活的代码结构。
|
6月前
|
JavaScript 安全 前端开发
高阶函数(js的问题)
高阶函数(js的问题)
33 0
|
6月前
|
存储 前端开发 JavaScript
JavaScript 中的高阶函数
JavaScript 中的高阶函数