定义
- 函数的参数是函数(回调)
- 函数的返回值是函数(拆分)
事务
- 作用是在核心方法之前和之后都扩展
- 注意:这里的事务是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 发布订阅