纯函数需满足以下两点:
- 一定(相同)的输入带来一定(相同)的输出
- 函数执行过程不产生副作用(修改全局变量,修改参数,修改外部存储例如localstorage)
var name = "李四"
function foo(){
return name
}
foo(123)
name = "王五"
foo(123) //此时输入相同,输出已经不一样了,foo就不符合纯函数了
数组的slice和splice都是分割数组的作用,但前者不会改变原数组,后者改变了,所以前者为纯函数,后者产生副作用,不是纯函数
函数柯里化:
只传递一部分参数调用一个函数,让它返回一个函数去处理剩余参数的过程(不一定拆成只携带一个参数,两个也行,只要有拆参数的过程就叫柯里化)简单图解:
柯里化好处:单一职责,每个函数只做自己要做的事情,函数式编程的规范,部分代码也可复用
简单实现一个柯里化函数生成器,只适用于简单逻辑:
function foo(a,b,c){
console.log(this);
console.log(a+b+c);
return a+b+c
}
//柯里化函数
function curring(fn){
function curried(...arg){
//参数没传完,执行下一个柯里化函数
if(arg.length >= fn.length){
return fn.apply(this,arg) //最终执行
}else{
function curryNext(...argNext){
return curried.apply(this,[...arg,...argNext])
}
return curryNext
}
}
return curried
}
var newFoo = curring(foo)
newFoo(1,2,3) // window 6
newFoo(1)(2,3) // window 6
newFoo(1)(2)(3) // window 6
newFoo.bind("234",1)().call("567",3).apply("345",[2]) //最后打印的this可以猜猜是什么
组合函数:
将要执行的函数传到一个函数里,然后直接调用这个函数,例如:
function foo(bar1,bar2){
return function(num){
return bar1(bar2(num))
}
}
var newFoo = foo(bar1,bar2)
newFoo(10)
简单实现一个组合函数处理器,只适用于简单逻辑:
function add(a){
console.log(this);
return ++a
}
function multip(b){
console.log(this);
return b*b
}
function composs(...arg){
//判断参数是否均为函数
for(let fn of arg){
if(typeof fn !== "function"){
throw new Error("类型错误,因传入函数")
}
}
var length = arg.length
return function(...newArg){
var index = 0
//如果组合函数没有传参,则直接返回后续函数的参数
var result = length>0 ? arg[index].apply(this,newArg) : newArg
//遍历执行所传函数
while(++index<length){
result = arg[index].apply(this,[result])
}
return result
}
}
var foo = composs(add,multip)
console.log(foo(2)) //9