JS纯函数 柯里化函数 组合函数

2022-04-25  本文已影响0人  咸鱼不咸_123

1.纯函数(Pure Function)

函数式编程中有一个非常重要的概念叫做纯函数,javascript符合函数式编程的范式,所以也有纯函数的概念

Vue3有一个setup函数——》编写很多其他的逻辑——》更加接近于原生开发——》函数的概念——》

1.1 维基百科的解释

在程序设计中,若一个函数符合以下条件,那么这个函数被称为纯函数

简单的总结

1.1.1 相同的输入值,产生不同的输出
var name="abc"
function foo(){
    return name;
}
foo(123)
name="123"
foo(123)

1.2 副作用的理解

副作用是什么?

后面编写js函数的时候,尽可能让函数只做一件事情,尽可能让函数的做的事情变的更简单

1.3 纯函数的练习


// * 是一个纯函数,确定的输入,产生确定的输出
// * 函数没有产生副作用
function foo(num1,num2){
  return num1+num2*num2;
}
// * 不是纯函数 
//* 产生了副作用,修改了外层的变量的值
var name="abc";
function bar(){
  console.log("bar其他的代码执行");
  name="cba";
}
bar()
//* 不是纯函数
//* 修改了参数的值,产生了副作用
function baz(info){
  info.age=100;
}
var obj={name:"wjy",age:15};
baz(obj);
console.log(obj);
//* 纯函数:相同的输入(值相同),产生相同的输出
function test(info){
  return{
    ...info,
    age:100
  }
}
1.3.1 争议的题
function printInfo(info){
  console.log(info.name,info.age);
}
1.3.2 总结

1.4 纯函数的优势

React非常灵活,但它也有一个严格的规则

所有React组件都必须像一个纯函数一样保护它们的props不被修改

纯函数修改一个对象,会在函数内部返回一个新的对象,在外部用一个对象进行接收

2.JavaScript柯里化(过程不是指函数)

柯里化也是属于 函数式编程 里面一个非常重要的概念。

2.1 维基百科的解释

我们先来看一下 维基百科 的解释 :

总结

function foo(m,n,x,y){
  return m+n+x+y;
}

//柯里化的过程
function bar(m){
  return function(n){
    return function(x){
      return function(y){
        return m+n+x+y;
      }
    }
  }
}

console.log(bar(10)(20)(30)(40));

2.2 柯里化结构

//未柯里化的函数
function add1(x,y,z){
  return x+y+z
}

console.log(add1(10,20,30));

// 柯里化处理的函数
function add2(x){
  return function(y){
    return function (z){
      return x+y+z;
    }
  }
}
console.log(add2(10)(20)(30));

//简化柯里化的代码
var add3=x=>y=>z=>{
  return x+y+z;
}

console.log(add3(10)(20)(30));

//未简化的箭头函数,只有执行体只有一句代码时,可以省略外面的大括号和return
var add4=x=>{
  return y=>{
    return x=>{
      return x+y+z
    }
  }
}
  


console.log(add4(10)(20)(30));

2.3 柯里化的作用

2.3.1 让函数的职责单一

那么为什么需要柯里化呢?

function add(x,y,z){
  x=x+2;
  y=y*2;
  z=z**2;
  return x+y+z;
}
console.log(add(10,20,30));

function sum(x){
  x=x+2;
  return function(y){
    y=y*2;
    return function(z){
      z=z**2;
      return x+y+z;
    }
  }
}

console.log(sum(10)(20)(30));
2.3.2 逻辑的复用
2.3.2.1 案例1
function sum(m,n){
  return m+n;
}

//假如在程序中,外面经常需要把5和另外一个数字进行相加
console.log(sum(5,10));
console.log(sum(5,6));
console.log(sum(5,100));
console.log(sum(5,555));

function  makeAdder(count){
  return function(num){
    return num+count;
  }
}

let add5=makeAdder(5);
console.log(add5(10));
console.log(add5(6));
console.log(add5(100));
console.log(add5(555));
2.3.2.2 案例2
// function log(date,type,message){
//   console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]:[${message}]`);
// }
// log(new Date(),"DEBUG","查找到轮播图的bug")
// log(new Date(),"DEBUG","查询菜单的bug")
// log(new Date(),"DEBUG","查询数据的bug")


// 柯里化优化 
var log=date=>type=>message=>{
  console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]:[${message}]`);
}

//如果我现在打印的都是当前时间 
var nowLog=log(new Date())
nowLog("DEBUG")("查找到轮播图的bug")
nowLog("FEATURE")("新增了添加用户的功能")

//如果打印的都是相同的时间和类型
var nowLogAndDebugLog=log(new Date())("DEBUG")
nowLogAndDebugLog("查找到轮播图的bug")
nowLogAndDebugLog("查询菜单的bug")
nowLogAndDebugLog("查询数据的bug")

var nowLogAndFeatureLog=log(new Date())("FEATURE")
nowLogAndFeatureLog("新增了添加用户的功能")

2.4 自动柯里化函数的实现

function add1(x,y,z){
  return x+y+z;
}

function add2(x,y,z){
  x=x+2;
  y=y*2;
  z=z**2;
  return x+y+z;
}
function makeAdder(count){
  return  function(num){
    return count+num;
  }
}

function log(date,type,message){
  console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]:[${message}]`);
}

//柯里化函数的实现hyCurrying
/**
 * 
 * @param {*} fn  
 * * 传入一个函数,返回一个新的函数
 */
function hyCurrying(fn){
  function curried(...args){
    // 判断当前已经接收的参数的个数,可以判断本身需要接受的参数是否一致了
    if(args.length>=fn.length){
      //接收的参数已经够了,需要去调用用来的参数
      // fn(...args) //这样写的话没有考虑后面绑定的this
      return  fn.apply(this,args)
    }else{
      // 如果个数没有达到,则返回一个新的函数
       function curried2(...args2){
        //  接收到参数后,需要递归调用curried来检查函数的个数是否达到
           return curried.apply(this,[...args,...args2])
      }
      return curried2;
    }
  }
  return curried;

}
var  curryAdd=hyCurrying(add1);

console.log(curryAdd(50)(20,30));

// function foo(a,b,c,d,e,f,g){

// }
// // 函数名.length获取参数的个数
// console.log(foo.length);

Vue3为什么使用柯里化,是为了可扩展性,

3.组合函数

组合(Compose)函数是在JavaScript开发过程中一种对函数的使用技巧、模式:

3.1 组合之前

function double(num){
  return num*2;
}
function square(num){
  return num**2;
}
var count=10;
var result=square(double(count));
console.log(result);

3.2 组合之后

function double(num){
  return num*2;
}
function square(num){
  return num**2;
}

var count=10;
var result=square(double(count));
console.log(result);

function composeFn(m,n){
  return function (count){
   return  m(n(count))
  }
}

var newFn=composeFn(square,double);
console.log(newFn(10));
console.log(newFn(20));
console.log(newFn(30));

3.3 通用组合函数的实现

function hyCompose(...fns){
  // * 需要考虑一些边界情况,例如传的有可能不是一个函数
  var length=fns.length;
  for(let i=0;i<length;i++){
    if(typeof fns[i]!=='function'){
      throw new TypeError("Expected arguments are functions")
    }
  }
  function compose(...args){

    let index=0;
    let result=length>0?fns[index].apply(this,args);
    while(++index<length){
      result=fns[index].call(this,result);
    }
    return result;

  }
  return compose; 
}

function double(m){
  return m*2;
}

function square(n){
  return n**2
}

var newFn=hyCompose(square,double);
console.log(newFn(10));

4.总结

纯函数、柯里化函数、组合函数.png
上一篇下一篇

猜你喜欢

热点阅读