高阶函数

定义

  1. 函数的参数是函数(回调)
  2. 函数的返回值是函数(拆分)

事务

  • 作用是在核心方法之前和之后都扩展
  • 注意:这里的事务是react中的概念,跟sql语句没有关系
const perform = (anyMethod, warppers) => {
    warppers.forEach( wrap => {
        wrap.initilizae();
    })
    anyMethod();
    warppers.forEach( wrap => {
        wrap.close();
    })
}
// 输出为您好1 您好2 说话 再见1 再见2
perform(() => {
    console.log('说话');
}, [{
        initilizae() {
            console.log('您好1');
        },
        close() {
            console.log('再见1');
        }

    },
    {
        initilizae() {
            console.log('您好2');
        },
        close() {
            console.log('再见2');
        }

    }
])

call,apply,bind三者的区别

  • 相同点都是用来改变this的指向。
  • 不同点,call的参数是一个一个的接受,立即执行;apply是第一个是this要指向的对象,第二个对象为数组,立即执行;bind方法在IE 6-8不支持,不是立即执行,而是返回一个改变了上下文后的函数,需要主动调用。
//例子:求数组中的最值 
let arr1 = [1, 2, 19, 6];
console.log(Math.max.call(null, 1,2,19,6)); // 19
console.log(Math.max.call(null, arr1)); // NaN
console.log(Math.max.apply(null, arr1)); //  19 直接可以用arr1传递进去

延时函数(调用几次后执行)

const deferred = (times, fn) => {
    return () => {
        if (--times === 0) {
            fn();
        }
    }
}
let newFn = deferred(3,()=>{
    console.log('三次后执行');
})
newFn();
newFn();
newFn(); // 这里调用攻击三次了,执行回调函数

实例: 解决并发问题,核心是计数器

let fs = require("fs"); // file system 读取文件 操作文件

let school = {};

function after(times,callback){ // 高阶函数, 发布订阅模式
    return function(){
        if(--times === 0){
            callback();
        }
    }
}
let out = after(2,function(){ // 将数量内置到after函数中,闭包 Promise.all
    console.log(school);
});
// 每次读取后 都调用out方法
fs.readFile('./name.txt','utf8',function(err,data){
    school['name'] = data;
    out();
})
fs.readFile('./age.txt','utf8',function(err,data){
    school['age'] = data;
    out();
})

 // 核心还是计数器
// 计数器的方式
// let index = 0;
// function out(){
//     index++;
//     if(index === 2){
//         console.log(school)
//     }
// }

发布订阅

  • 有一个数组可以存放函数
  • 有一个订阅方法on,接受函数作为参数
  • 有一个触发方法emit,遍历数组中的函数
let fs = require('fs');
// 发布订阅 和 观察者模式的区别(基于发布订阅的) vue 观察者模式 es6的用法
let school = {}; // vue eventBus
let event = {
    arr:[], // 中介
    on(fn){
        this.arr.push(fn); // 把函数存到数组中,注意这里的this
    },
    emit(){
        this.arr.forEach(fn=>fn()); // 发布
    }
}
event.on(function(){
    console.log('读取一次')
})
event.on(function(){
    if(Object.keys(school).length === 2){
        console.log(school);
    }
})
fs.readFile('./name.txt','utf8',function(err,data){
    school['name'] = data;
    event.emit(); // 发布
})
fs.readFile('./age.txt','utf8',function(err,data){
    school['age'] = data;
    event.emit(); // 发布
})

发布订阅是观察者模式的一部分,
发布和订阅是没有关系的,有一个数组作为第三方空间;
观察者是观察者绑定了被观察者,也就是被观察者中有一数组存放着观察者对象,有关联关系。

观察者

  • 两个对象,一个观察者,一个被观察者
  • 被观察者的构造函数中有一个数组存放观察者对象,有一个状态;有一个挂载观察者的方法,一个更新状态的方法
  • 观察者有一个更新的方法,当被观察者的状态更新的时候可以被调用
// 被观察者 
class Subject { 
    constructor(){
        this.arr = []; // 数组中存放的是观察者的实例
        this.state = '开心';
    }
    setState(newState){
        this.state = newState;
        this.arr.forEach(o=>o.update(this))
    }
    attach(o){ // 挂载观察者
        this.arr.push(o);
    }
}

// 观察者
class Observer{ 
    constructor(name){ this.name = name;}
    update(s){ // 当前被观察者的状态发生了变化,需要更新状态了
        console.log(s.state+'对:'+this.name)
    }
}
let s = new Subject('小宝宝');  // 创建被观察者
let o1 = new Observer('我'); // 创建两个观察者
let o2 = new Observer('媳妇');
s.attach(o1);
s.attach(o2);
s.setState('不开心')

vue 观察者模式 eventBus 发布订阅

上一篇:网络子系统15_arp邻居项初始化


下一篇:php字节码缓存之opcache