//2020-node1
//1、before方法
//什么是高阶函数:
//1、如果一个函数的参数是一个函数(回调函数就是一种高阶函数)
//2、如果一个函数返回一个函数,当前这个函数也是一个高阶函数
//高阶函数的应用场景:为了稍后写promise作铺垫
//写了一个业务代码,扩展当前的业务代码
function say(){
console.log('say');
}
//给某个方法添加一个方法在他执行之前调用
Function.prototype.before=function(callback){
let that = this;
return function(){
callback();
that();
}
}
//替换成箭头函数实现
Function.prototype.before=function(callback){
return ()=>{
callback();
this();
}
}
let beforeSay = say.before(function(){
console.log('before say');
});
beforeSay();
//传参
function say(a,b){
console.log(a,b);
}
Function.prototype.before = function(callback){
return (...args)=>{//剩余运算符,箭头函数没有this,也没有arguments
callback();
say(...args);//展开运算符
}
}
let beforeSay = say.before(function(){
console.log('before say');
});
beforeSay('hello','world');
//2、函数柯里化
//判断变量的类型:
//1、typeof 不能判断对象类型 typeof [] ->"object" typeof {} ->"object"
//2、constructor 可以找到这个变量是通过谁构造出来的
//3、instanceof 判断谁是谁的实例 __proto__
//4、Object.prototype.toString.call() 缺陷就是不能细分谁是谁的实例
function isType(value,type){
return Object.prototype.toString.call(value) === `[object ${type}]`;
}
//能不能将方法细分 isType => isString isArray
//console.log(isType([],'Aray'));//false
function isType(type){
return function(value){
return Object.prototype.toString.call(value) === `[object ${type}]`;
}
}
let isArray = isType('Array');
console.log(isArray('hello'));//false
console.log(isArray([])); //true Object.prototype.toString.call([]) -->"[object Array]"
//例如:
//function sum(a,b,c,d,e,f)
//{
// return a+b+c+d+e+f;
//}
//let r = currying(sum)(1,2)(3,4)(5)(6)
function isType(type,value){
return Object.prototype.toString.call(value) === `[object ${type}]`;
}
const currying=(fn, arr=[])=>{
let len = fn.length; //这里获取的是函数的参数的个数
return function(...args){ //高阶函数
let concatValue = [...arr,...args];
if(concatValue.length < len){
return currying(fn,concatValue); //递归不停的产生函数
}
else
{
return fn(...concatValue);
}
}
}
let isArray = currying(isType)('Array');
let isString = currying(isType)('String');
console.log(isArray([])); //true
console.log(isString('123'));//true
//例如:
/*
function sum(a,b,c,d,e,f)
{
return a+b+c+d+e+f;
}
const currying=(fn, arr=[])=>{
let len = fn.length; //这里获取的是函数的参数的个数
return function(...args){ //高阶函数
let concatValue = [...arr,...args];
if(concatValue.length < len){
return currying(fn,concatValue); //递归不停的产生函数
}
else
{
return fn(...concatValue);
}
}
}
let r = currying(sum)(1,2)(3,4)(5)(6)
console.log(r);//21
*/
function sum(a,b,c,d,e,f)
{
return a+b+c+d+e+f;
}
const currying=(fn, arr=[])=>{
let len = fn.length; //这里获取的是函数的参数的个数
return function(...args){ //高阶函数
console.log(args);
arr = [...arr,...args];
if(arr.length < len){
return currying(fn,arr); //递归不停的产生函数
}
else
{
return fn(...arr);
}
}
}
let r = currying(sum)(1,2)(3,4)(5)(6)
console.log(r);
<!------------------------------------->
//3、通过回调函数异步并发问题
//多个异步请求,如何同时获取最终结果
/*
let fs = require('fs');
fs.readFile('./name.txt','utf8',function(err,data){ //异步
console.log(data);
})
fs.readFile('./age.txt','utf8',function(err,data){ //异步
console.log(data);
})
*/
let fs = require('fs');
let school = {};
let index = 0;
const cb = ()=>{
if(++index === 2){
console.log(school);
}
}
fs.readFile('./name.txt','utf8',function(err,data){
school.name = data;
cb();
})
fs.readFile('./age.txt','utf8',function(err,data){ //异步
school.age = data;
cb();
})
//用闭包实现
let fs = require('fs');
let school = {};
function after(times,callback){
return function(){ //闭包
if(--times === 0){
callback();
}
}
}
let cb = after(2, function(){
console.log(school);
});
fs.readFile('./name.txt','utf8',function(err,data){
school.name = data;
cb();
});
fs.readFile('./age.txt','utf8',function(err,data){
school.age = data;
cb();
})
//什么是闭包?
//函数定义的作用域和函数执行的作用域不在同一个作用域下
//4、发布订阅模式
//发布订阅模式 主要分成两个部分 on emit
//on就是把一些函数维护到一个数组中
//emit就是让数组中的方法依次执行
let fs = require('fs');
let school = {};
//租赁房屋
let event = {
arr:[],
on(fn){
this.arr.push(fn);
},
emit(){
this.arr.forEach(fn=>fn());
}
}
event.on(function(){
console.log('读取完毕');
});
event.on(function(){
console.log('读取完毕1');
});
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();
});
//结果:
//读取完毕
//读取完毕1
//读取完毕
//读取完毕1
let fs = require('fs');
let school = {};
//租赁房屋
let event = {
arr:[],
on(fn){
this.arr.push(fn);
},
emit(){
this.arr.forEach(fn=>fn());
}
}
event.on(function(){
console.log('读取了一个');
});
event.on(function(){
if(Object.keys(school).length === 2) //Object.keys(obj)参数:要返回其枚举自身属性的对象; 返回值:一个表示给定对象的所有可枚举属性的字符串数组
{
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();
});
//结果:
//读取了一个
//读取了一个
//{ name: 'zf', age: '10' }
//5、观察者模式
//观察者模式 有观察者 肯定有被观察者 观察者需要放到被观察者中,被观察者的状态发生变化,需要通知观察者:我变化了。
//内部也是基于发布订阅模式,收集观察者 ,状态变化后要通知观察者
class Subject{
constructor(name){ //被观察者 小宝宝
this.name = name;
this.state = '开心的';
this.observers = [];
}
attach(o){ //Subject.prototype.attach
this.observers.push(o); //收集观察者
}
setState(newState){
this.state = newState;
this.observers.forEach(o=>o.update(this)) //当状态变化通知观察者
}
}
class Observer{ //观察者 我 我媳妇
constructor(name){
this.name = name;
}
update(baby){
console.log('当前'+this.name +'被通知了','当前小宝宝的状态是'+baby.state);
}
}
//我和我媳妇需要观察小宝宝的心理状态的变化
let baby = new Subject('小宝宝');
let parent = new Observer('爸爸');
let mother = new Observer('妈妈');
baby.attach(parent);
baby.attach(mother);
baby.setState('被欺负了');