高阶函数
Posted bonly-ge
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高阶函数相关的知识,希望对你有一定的参考价值。
定义
- 函数的参数是函数(回调)
- 函数的返回值是函数(拆分)
事务
- 作用是在核心方法之前和之后都扩展
- 注意:这里的事务是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 发布订阅
以上是关于高阶函数的主要内容,如果未能解决你的问题,请参考以下文章