//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.isString.call(value) === `[object ${type}]`;
}
const currying=(fn, arr=[])=>{
let len = fn.length; //這裏獲取的是函數的參數的個數
return function(...args){ //高階函數
let concatValue = [...arr,...args];
if(arr.length < len){
return currying(fn,concatValue); //遞歸不停的產生函數
}
else
{
return fn(...concatValue);
}
}
}
let isArray = currying(isType)('Array');
let isString = currying(isType)('String');
console.log(isArray([]));
console.log(isArray('123'));
<!------------------------------------->
//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('讀取完畢');
});
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();
});
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();
});
//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('被欺負了');