js函数柯里化 简单理解,js函数柯里化实现

  js函数柯里化 简单理解,js函数柯里化实现

  本文给大家带来了一些关于javascript的知识,主要介绍了JavaScript中函数类化的相关问题。科里化是将接受多个参数的函数转化为接受单个参数的函数,并返回接受其余参数的新函数并返回结果的技术。希望对你有帮助。

  推荐:javascript教程

  

一、简单了解apply和call

  调用并应用exist来更改函数运行时的上下文,换句话说,更改函数体内部的上下文方向。call apply和call apply的功能完全一样,只是接受参数的方式不同。Call其实是apply的语法糖。格式为:apply(上下文,[参数]),call(上下文,参数1,参数2,).

二、什么是函数柯里化?

   Currying是将接受多个参数的函数转换为接受单个参数(原函数的第一个参数)的函数,并返回接受其余参数的新函数并返回结果的技术。

  例如,这里有一个add()函数,这个函数用于处理我们传递给它的参数(param1,params2,…)的相加和求和。

  //这里的第一个add(x,y)`函数有两个参数` x`、` y`。

  函数add(x,y){

  返回x y;

  }

  //调用 add()函数并给出两个参数 4 和 6 。

  添加(4,6);

  //模拟计算机操作,第一步是传入第一个参数4

  函数add(4,y){

  返回4y;

  }

  //模拟计算机操作,第二步是传入第一个参数6

  函数add(4,6){

  返回4 6;

  }如果我们将add()函数柯里化,会是什么样子?下面是一个简单的实现:

  //Corinized add()函数,可以接受一些参数

  函数add(x,y){

  if (typeof y===undefined) {

  返回函数(newy){

  返回x newy

  }

  }

  //完成应用程序

  返回x y;

  }

  //测试调用

  console.log(添加类型(4));//[功能]

  console . log(add(4)(6));//10

  //你可以创建一个保存函数

  设save add=add(4);

  console . log(save add(6));//10从上面简单的Corinized add()函数可以看出,函数可以接受一部分函数,然后返回一个新的函数继续处理剩下的。

  

三、写一个公共的柯里化函数

  这里我们创建了一个公共的科里化函数,这样我们就不用每次写函数的时候都在里面实现一个复杂的科里化过程。

  //定义一个createCurry函数createCurry(fn){

  var slice=Array.prototype.slice

  stored _ args=slice . call(arguments,1);

  返回函数(){

  let new _ args=slice . call(arguments),

  args=stored _ args . concat(new _ args);

  返回fn.apply(null,args);

  }}在上面的公共科里奥利函数中:

  Arguments,不是一个真正的数组,只是一个具有length属性的对象,所以我们借用Array.prototype的slice方法来帮助我们把arguments变成一个真正的数组,方便我们更好的操作。当我们第一次调用函数createCurry时,变量stored_args保留了除第一个参数之外的参数,因为第一个参数是我们需要进行corialize的函数。当我们执行createCurry函数中返回的函数时,变量new_args获取参数并将它们转换成数组。返回的函数通过闭包将存储在变量stored_args中的值和变量new_args的值访问到一个新数组中,并将其赋给变量args。最后,调用fn.apply(null,args)方法来执行corified函数。现在我们来测试公共的柯里化函数

  //普通函数add()

  函数add(x,y){

  返回x y;

  }

  //cori ization以获取新函数

  var newAdd=createCurry(add,4);

  console . log(new add(6));//10

  //另一个简单的方法

  console.log(createCurry(add,4)(6));//10当然,这里并不局限于两个参数的科里奥利,还可以有多个参数:

  //具有多个参数的通用函数

  函数add(a,b,c,d){

  返回a b c d;

  }

  //Corinize函数得到一个新的函数,多个参数可以随机划分。

  console.log(createCurry(add,4,5)(5,6));//20

  //两步cori化

  设add_one=createCurry(add,5);

  console.log(add_one(5,5,5));//20

  设add_two=createCurry(add_one,4,6);

  console . log(add _ two(6));//21通过上面的例子,我们可以发现一个限制,就是无论是两个参数还是多个参数,都只能分两步执行,比如下面的公式:

  fn(x,y)==fn(x)(y);Fn (x,y,z,w)==fn (x) (y,z,w) fn (x,y) (z,w) …如果我们想要更灵活:

  fn(x,y)==fn(x)(y);fn(x,y,z)==fn(x,y)(z) fn(x)(y)(z);fn(x,y,z,w)==fn(x,y)(z)(w) fn(x)(y)(z)(w) …;如何才能实现这一点?

  

四、创建一个灵活的柯里化函数

  经过以上练习,我们发现我们创建的科里奥利函数有一定的局限性。我们希望该功能可以分多个步骤执行:

  //创建一个可分多步执行的科里奥利函数,当参数满足数量时执行:

  //函数公式:fn(x,y,z,w)==fn(x)(y)(z)(w);

  let createCurry=(fn,params)={

  let args=par SMS [];

  设fnLen=fn.length//指定科里奥利函数的参数长度

  返回(.res)={

  //通过作用域链获取上一次的所有参数。

  设allArgs=args . slice(0);

  //深度复制由闭包共享的args参数,以避免后续操作的影响(引用类型)

  allArgs.push(.RES);

  if(allArgs.length fnLen){

  //当参数个数小于原函数长度时,递归调用createCurry函数。

  返回createCurry.call(this,fn,allArgs);

  }否则{

  //当满足参数个数时,触发函数执行

  return fn.apply(this,allArgs);

  }

  }

  }

  //具有多个参数的通用函数

  函数add(a,b,c,d){

  返回a b c d;

  }

  //测试科里奥利函数

  let curryaddd=create curry(add,1);

  console . log(curryaddd(2)(3)(4));//10上面,我们已经实现了灵活的科里奥利函数,但是在这里我们发现了另一个问题:

  如果我第一次传入了所有的参数,但没有返回结果,那就是一个函数。只有再次调用返回的函数,才能返回结果:curryaddd(add,1,2,3,4)();有人可能会说,如果所有参数都通过了,就调用原来的add()函数,也是一个办法;但既然是来满足参数个数的,那就最好处理一下这种情况。这里我们只需要在返回函数之前做一个判断:

  let createCurry=(fn,params)={

  let args=par SMS [];

  设fnLen=fn.length//指定科里奥利函数的参数长度

  if(length===_args.length){

  //加入判断,如果第一次参数个数足够,直接调用函数得到结果。

  返回fn.apply(this,args);

  }

  返回(.res)={

  设allArgs=args . slice(0);

  allArgs.push(.RES);

  if(allArgs.length fnLen){

  返回createCurry.call(this,fn,allArgs);

  }否则{

  return fn.apply(this,allArgs);

  }

  }}以上可以看作是一个灵活的科林斯函数,但是在这里并不是很灵活,因为我们无法控制它什么时候执行,只要参数足够多就会自动执行。如果我们想实现一个我们可以控制其执行的时间,我们应该怎么做?

  

五、写一个可控制的执行时间的柯里化函数

  这里直接解释函数公式吧:

  fn(a,b,c)==fn(a)(b)(c)();fn(a,b,c)==fn(a);fn(b);fn(c);fn();当我们有足够的参数时,它不会执行。只有当我们再次调用函数时,它才会执行并返回结果。这里我们可以通过在上面的例子中添加一个小条件来实现。//当参数满足时调用函数并再次执行

  let createCurry=(fn,params)={

  let args=par SMS [];

  设fnLen=fn.length//指定科里奥利函数的参数长度

  //当然这里的判断需要注释掉,否则会在第一次参数个数足够的时候直接执行结果。

  //if(length===_args.length){

  //加入判断,如果第一次参数个数足够,直接调用函数得到结果。

  //返回fn.apply(this,args);

  //}

  返回(.res)={

  设allArgs=args . slice(0);

  allArgs.push(.RES);

  //这里判断输入参数是否大于0。如果大于0,判断参数个数是否足够,

  //这里不能用。如果使用的话,结果会在参数个数足够的时候执行。

  if(RES . length 0 all args . length fnLen){

  返回createCurry.call(this,fn,allArgs);

  }否则{

  return fn.apply(this,allArgs);

  }

  }

  }

  //具有多个参数的通用函数

  函数add(a,b,c,d){

  返回a b c d;

  }

  //测试可控科里奥利函数

  let curryaddd=create curry(add,1);

  console . log(curryaddd(2)(3)(4));//函数

  console . log(curryaddd(2)(3)(4)());//10

  console . log(curryAdd(2)(3)());//参数不够时,返回NaN相关推荐:javascript学习教程。以上就是讲JavaScript函数的cori化的细节。更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: