高阶函数一

146 阅读2分钟

高阶函数

一个函数做为另一个函数的参数,或者返回值

作用:包装函数,装饰器

before

    function makeCoffee(){
        console.log('做咖啡')
    }
    Function.prototype.before = function(fn){
        return ()=>{
            fn();
            this();
        }
    }
    
    let newFn = makeCoffee.before(()=>{
        console.log('加糖')
    })
    
    newFn(); 
    // 输出: 
    //     加糖
    //     做咖啡
    
    

React 事务

function affair(arr,fn){
    return ()=>{
        
        arr.forEach(v=>v.init())
        fn();
        arr.forEach(v=>v.end())
        
    }
}

let newFn = affair([
  {
    init() {
      console.log('init');
    },
    end() {
      console.log('end');
    },
  },
  {
    init() {
      console.log('init2');
    },
    end() {
      console.log('end2');
    },
  },
], function () {
  console.log('xxxx');
});

newFn();

/**
*  输出:
*      init
*.     init2
*.     xxxx
*.     end
*.     end2
*/

函数柯粒化

将一个有多个参数的函数,分布执行


function add(a,b,c,d,e){
    return a + b + c + d + e;
}

function curry(fn,lenArr = []){
    return (...args)=>{
        lenArr = [...lenArr,...args];
        if(lenArr.length === fn.length){
            return fn(...lenArr);
        }else{
            return curry(fn,lenArr);
        }
    }
}

let newFn = curry(add)(1)(2);

console.log(newFn);  // [Function]

let r = newFn(3)(4)(5)

console.log(r);   // 15

解决异步的方案: callback


const fs = require('fs')
const path = require('path')

function getData(name,callback){
    fs.readFile(path.resolve(__dirname,name),function(err,data){
        if(err){
            console.log(err)
            return;
        }
        callback(data)
    })
}

getData('a.txt',(data)=>{
    console.log(data)
})

闭包

一个函数不在当前作用域下执行

  • 作用1:隐藏变量,避免全局污染

  • 作用2:可以读取函数内部的变量

  • 缺点:造成内存泄漏

解决异步并发问题

  1. 计数器

    const fs = require('fs')
    const path = require('path')
    
    let obj = {};
    fs.readFile(path.resolve(__dirname,'a.txt'),(err,data)=>{
        if(err){
            console.log(err)
            return;
        }
         console.log(data.toString()) // aaaa
         obj['a'] = data.toString();
         allResolve();
    })
        
    
    fs.readFile(path.resolve(__dirname,'b.txt'),(err,data)=>{
        if(err){
            console.log(err)
            return;
        }
        console.log(data.toString()) // bbbb
        obj['b'] = data.toString();
        allResolve();
    })
       
    function calcNum(){
        let num = 2;
        return ()=>{
            if(--num === 0){
                console.log(obj) // { a: 'aaaa', b: 'bbbb'}
            }
        }
    }
    
    let allResolve = calcNum();
    
    
    
    

  1. 发布订阅

    const fs = require('fs')
    const path = require('path')
    
    let observe = {
        arr: [],
        on(fn){
            this.arr.push(fn)
        },
        emit(){
            this.arr.forEach(fn=>fn())
        }
    }
    
    // 订阅
    observe.on(function(){
        console.log(obj);
    })
    
    let obj = {};
    fs.readFile(path.resolve(__dirname,'a.txt'),(err,data)=>{
        if(err){
            console.log(err)
            return;
        }
         console.log(data.toString()) // aaaa
         obj['a'] = data.toString();
         // 发布
         observe.emit();
    })
        
    
    fs.readFile(path.resolve(__dirname,'b.txt'),(err,data)=>{
        if(err){
            console.log(err)
            return;
        }
        console.log(data.toString()) // bbbb
        obj['b'] = data.toString();
        // 发布
        observe.emit();
    })
    


观察者模式

观察者模式与发布订阅的区别

  • 观察者模式 包含 发布订阅模式; 除了发布订阅,里面还包含观察者和被观察者;
// 观察者
class Observer {
    constructor(name){
        this.name = name;
    }
    update(o){
        console.log('状态更新了')
        console.log(o.state)
    }

}
// 被观察者
class Subject {
    constructor(name){
        this.name = name;
        this.state = '开心'
        this.arrFn = [];
    }
    
    setState(value){
        this.state = value;
        this.arrFn.forEach(v=>v.update(this))
    }
    
    attach(o){
        this.arrFn.push(o)
    }
    
}

let baobao = new Subject('baobao')
let mama = new Observer('mama')
let baba = new Observer('baba')

baobao.attach(mama) // 添加观察者
baobao.attach(baba) // 添加观察者

baobao.setState('不开心') //被观察者状态更新了,通知观察者