Js高阶函数(Heigher-order function)

更新日期: 2019-07-22阅读: 1.8k标签: 函数

概念

《javascript设计模式和开发实践》中定义 函数既可作为参数被传递,也可以作为返回值输出  

满足以下条件:

  1. 接受一个或多个函数作为输入
  2. 输出一个函数

高阶函数一般是那些函数型包含多于函数。在函数式编程中,返回另一个函数的高阶函数被称为Curry化的函数。


函数作为参数传递

将函数作为参数传递,我们就可以抽离以部分容易变化的业务逻辑,这样可以分离业务代码中变与不变的部分  

回调函数:

将函数传进一个方法中,函数不会立即执行,等待出来结果之后在执行。  

let func = function (callback){
    if(n === 'owen'){
        callback() //回调函数
    }
}
 function say (){
     console.log('Hello Word')
 }
 func(say)

Array 对象常用的方法

[1,2,3,4].forEach(iteration)
 function iteration(v){
     console.log(v)
 }


作为返回值输出

让函数继续返回一个可执行的函数,意味着运行过程是可延续的。  

判断数据类型

let type = type =>{
    return obj => Object.prototype.toString.call(obj) === `[object ${type}]`
}
let isArray = type('Array'),isString = type('String'),isNumber = type('Number'),isObject = type('Object');

// or
let Type = (function(){
    let type = {},types = ['Object','Array','Number','String']
    for (let val of  types) {
        (function(str){
            type[`is${str}`] = (obj) => Object.prototype.toString.call( obj ) === `[object ${str}]`
        }(val))
    }
    console.log(type)
    return type
}())
Type.isNumber(2) // true

实现AOP(面向切片编程)

AOP 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。JAVA 语言中 AOP 将一些跟核心业务逻辑模块无关的功能抽离出来,通常包括日志统计、安全控制、异常处理灯。再通过“动态织入”的方式掺入业务逻辑中。  

好处: 可以保持业务逻辑模块的纯净和高内聚,方便复用日志统计等功能模块。

JavaScript中实现AOP是指把一个函数“动态织入”到另一个函数之中

具体实现:

Function.prototype.before = function(beforeFn){
    let that = this; // 谁调用指向谁 下面是由 func 函数调用所以是指向 func

    return function( ...args){
        beforeFn.apply(this,args) // 执行回调函数 beforeFn
        return that.apply(this,args) // 执行原函数
    }
}

Function.prototype.after = function(afterFn){
    let that = this; // 谁调用指向谁 下面是由befor函数调用所以是指向 befor
    return function( ...args){
        let ret = that.apply(this,args) // 执行并接收原对象
        afterFn.apply(this,args) //  执行回调函数 beforeFn
        return ret
    }
}
var func = function (){
    console.log(2)
}
func = func.before(function (){
    console.log(1)
}).after(function (){
    console.log(3)
})
func()
// 1 2 3


函数柯里化 (function currying)

在数学和计算机科学中,柯里化是将多个参数的函数转换成一系列使用一个参数的函数,且返回接受余下的参数的新函数  

curring 又称部分求值;一个 curring 函数首先会接收一些参数,该函数并不会立即求值,而是继续返回另外一个函数,而刚传入的参数会被保存在形成的闭包中,待函数真正需要求值的时候,之前的所以参数都会被一次性用于求值

简单示例:

function add(a,b) {
    return a + b
}
add(1,2) // 3

接下来使用 currying 实现一个几天之内消费总和的函数

// 普通方法
var cost = (function() {
    var args = [];
    return function(){
        if(!arguments.length){
            let money = 0
            for (let val of args ){
                money += val;
            }
            return money
        }else{
            [].push.apply(args,arguments)
        }
    }
})()
cost(100);
cost(100);
cost(100);
cost(); // 300


// currying
/**
 * 保存原函数参数返回到新函数中使用
 */

//  func(100,100,100) //300
function count (...args){
    let num = 0;
     if(args.length>1){
         for (let v of args){
             num +=v
         }
         return num
     }else{
         return args[0]
     }
}

var  curry = function(func){
        let args = []
    return function fn(...Args){
        if (Args.length){
            [].push.apply(args,Args)
            return fn
        }else{
            return func.apply(this,args)
        }
    }
}
cost = curry(count);

cost(100);
cost(100);
cost(100);
cost(); // 300


函数节流

JavaScript 中大多数情况都是用户主动出发函数,除非函数本身的实现不合理,否则一般不会遇到跟性能相关的问题,少数情况下,函数不是由用户直接触发控制,可能被频繁调用造成严重的性能问题。
比如:

window.addEventListener('resize', function(e) {
   // do something...
});
window.addEventListener('scroll', function(e) {
   // do something...
});
dom.addEventListener('mousemove', function(e) {
   // do something...
});

// progress
xhr.upload.addEventListener("progress", function(result) {
    // do something...
}, false);

// ...

上述事件1秒种触发很多次,并且常常操作DOM节点,非常损耗性能,浏览器会因此吃不消而卡顿;实际我们不需要触发如此高的频率因此我们可以在一段时间内忽略掉一些执行次数

节流原理:

如果持续触发事件,可每隔一段时间只执行一次。  

使用定时器实现节流

将即将被执行的函数用 setTimeout 函数延迟一段时间执行,如果该定时器未执行完成则忽略接下下来的需被执行的函数。

 function throttle(func,wait) {
      let timer, firstFlag = true; //第一次立即执行
      return function(...args) {
          if(timer)  return false; // 如果存在定时器这不执行

          let that = this;
          if(firstFlag){
              firstFlag = false;
             return func.apply(that,args);
          }
          timer = setTimeout(function(){
               clearTimeout(timer);
               timer = null;
               func.apply(that,args);
            },wait)
      }
 }
 window.addEventListener('scroll', throttle(function(e) {
  console.log(e) 
},1000));


函数防抖

和节流一定时间段内只调用一次事件处理函数不同,防抖是一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。(用户不再触发对应事件才执行一次事件)

function debounce(func,wait) {
    let timer;
    return function(...args) {
        let that = this;
        clearTimeout(timer);
        timer = setTimeout(function(){
            func.apply(that,args)
        },wait)
    }
}
 window.addEventListener('scroll', debounce(function(e) {
  console.log(e) 
},1000));
来自:https://owen027.github.io/2019/07/12/designPatterns3/


链接: https://fly63.com/article/detial/4317

JavaScript 函数式编程

我理解的 JavaScript 函数式编程,都认为属于函数式编程的范畴,只要他们是以函数作为主要载体的。

Js函数式编程,给你的代码增加一点点函数式编程的特性

给你的代码增加一点点函数式编程的特性,最近我对函数式编程非常感兴趣。这个概念让我着迷:应用数学来增强抽象性和强制纯粹性,以避免副作用,并实现代码的良好可复用性。同时,函数式编程非常复杂。

让我们来创建一个JavaScript Wait函数

Async/await以及它底层promises的应用正在猛烈地冲击着JS的世界。在大多数客户端和JS服务端平台的支持下,回调编程已经成为过去的事情。当然,基于回调的编程很丑陋的。

JavaScript函数创建的细节

如果你曾经了解或编写过JavaScript,你可能已经注意到定义函数的方法有两种。即便是对编程语言有更多经验的人也很难理解这些差异。在这篇博客的第一部分,我们将深入探讨函数声明和函数表达式之间的差异。

编写小而美函数的艺术

随着软件应用的复杂度不断上升,为了确保应用稳定且易拓展,代码质量就变的越来越重要。不幸的是,包括我在内的几乎每个开发者在职业生涯中都会面对质量很差的代码。这些代码通常有以下特征:

javascript回调函数的理解和使用方法(callback)

在js开发中,程序代码是从上而下一条线执行的,但有时候我们需要等待一个操作结束后,再进行下一步操作,这个时候就需要用到回调函数。 在js中,函数也是对象,确切地说:函数是用Function()构造函数创建的Function对象。

js调用函数的几种方法_ES5/ES6的函数调用方式

这篇文章主要介绍ES5中函数的4种调用,在ES5中函数内容的this指向和调用方法有关。以及ES6中函数的调用,使用箭头函数,其中箭头函数的this是和定义时有关和调用无关。

JavaScript中函数的三种定义方法

函数的三种定义方法分别是:函数定义语句、函数直接量表达式和Function()构造函数的方法,下面依次介绍这几种方法具体怎么实现,在实际编程中,Function()构造函数很少用到,前两中定义方法使用比较普遍。

js在excel的编写_excel支持使用JavaScript自定义函数编写

微软 称excel就实现面向开发者的功能,也就是说我们不仅可以全新定义的公式,还可以重新定义excel的内置函数,现在Excel自定义函数增加了使用 JavaScript 编写的支持,下面就简单介绍下如何使用js来编写excel自定义函数。

js中的立即执行函数的写法,立即执行函数作用是什么?

这篇文章主要讲解:js立即执行函数是什么?js使用立即执行函数有什么作用呢?js立即执行函数的写法有哪些?

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!