2020-node-primse(1-5)

//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('被欺負了');

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章