You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionshowMsg(name,age,fruit){console.log('My name is '+name+', I\'m '+age+' years old, '+' and I like eat '+fruit);}varcurryingShowMsg1=curryingHelper(showMsg,'sadhu');curryingShowMsg1(21,'apple');console.log('---');varcurryingShowMsg2=curryingHelper(showMsg,'sadhu',21);curryingShowMsg2('apple');console.log('---');varcurryingShowMsg3=curryingHelper(showMsg);curryingShowMsg3('sadhu',21,'apple');/* 输出 My name is sadhu, I'm 21 years old, and I like eat apple---My name is sadhu, I'm 21 years old, and I like eat apple---My name is sadhu, I'm 21 years old, and I like eat apple*/
// 验证一下functionshowMsg(name,age,fruit){console.log('My name is '+name+', I\'m '+age+' years old, '+' and I like eat '+fruit);}varbetterShowMsg=betterCurryingHelper(showMsg);betterShowMsg('sadhu',21,'apple');console.log('---');betterShowMsg('sadhu',21)('apple');console.log('---');betterShowMsg('sadhu')(21,'apple');console.log('---');betterShowMsg('sadhu')(21)('apple');/* 输出My name is sadhu, I'm 21 years old, and I like eat apple---My name is sadhu, I'm 21 years old, and I like eat apple---My name is sadhu, I'm 21 years old, and I like eat apple---My name is sadhu, I'm 21 years old, and I like eat apple*/
什么是柯里化
wiki上这样定义:
柯里化又称部分求值,字面意思就是不会立刻求值,而是到了需要的时候再去求值。
举个例子:
函数add是一般的一个函数,就是将传进来的参数a和b相加;函数curryingAdd就是对函数add进行柯里化的函数;这样一来,原来我们需要直接传进去两个参数来进行运算的函数,现在需要分别传入参数a和b。
为什么要这样做?
总之,函数的柯里化能够让你重新组合你的应用,把你的复杂功能拆分成一个一个的小部分,每一个小的部分都是简单的,便于理解的,而且是容易测试的。
如何对函数进行柯里化
由浅入深讲解如何对一个多参数的函数进行柯里化。
第一步(浅)
假如我们要实现一个功能,就是输出语句name喜欢song,其中name和song都是可变参数;那么一般情况下我们会这样写:
对print函数进行柯里化后的函数应该是这样:
第二步(中)
上面我们虽然对函数print进行了柯里化,但是我们可不想在需要柯里化的时候,都像上面那样不断地进行函数的嵌套,这样代码会很难看,也不容易维护了。所以我们要创造一些帮助其它函数进行柯里化的函数来解决这个问题,我们暂且叫它为curryingHelper吧,一个简单的curryingHelper函数如下所示:
验证一下?
证明,我们这个柯里化的函数是🙆的。这里的curryingHelper就是一个高阶函数,函数为参数,返回值也是函数。
第三步(深)
上面的柯里化帮助函数确实已经能够达到我们的一般性需求了,但是它还不够好,我们希望那些经过柯里化后的函数可以每次只传递进去一个参数,然后可以进行多次参数的传递,拿上面的例子来说,就是在能实现curryingHelper的返回函数的调用方式的基础上再实现如下这样传:
动下脑筋,写一个betterCurryingHelper函数来实现:
curryingHelper()是第二步里的那个函数。这里的代码其实没啥难度,关键在于你能不能理清递归的过程。理解不了的仔细多看看。
验证一下?
成功,刺激。
一个应用场景:给setTimeout传递地进来的函数添加参数。
一般情况下,我们如果想给一个setTimeout传递进来的函数添加参数的话,一般会使用这种方法:
我们使用了一个新的匿名函数包裹我们要执行的函数,然后在函数体里面给那个函数传递参数值.
当然,在ES5里面,我们也可以使用函数的bind方法,如下所示:
这样也是非常的方便快捷,并且可以绑定函数执行的上下文.
我们本篇文章是讨论函数的柯里化,当然我们这里也可以使用函数的柯里化来达到这个效果:
这样也是可以的,是不是很酷.其实函数的bind方法也是使用函数的柯里化来完成的。可以看这里:深入js之造bind轮子。
关于柯里化的性能
当然,使用柯里化意味着有一些额外的开销;这些开销一般涉及到这些方面,首先是关于函数参数的调用,操作arguments对象通常会比操作命名的参数要慢一点;还有,在一些老的版本的浏览器中arguments.length的实现是很慢的;直接调用函数fn要比使用fn.apply()或者fn.call()要快一点;产生大量的嵌套作用域还有闭包会带来一些性能还有速度的降低.但是,大多数的web应用的性能瓶颈时发生在操作DOM上的,所以上面的那些开销比起DOM操作的开销还是比较小的。
本文完。
希望看到各位技术人对这篇文章有不同的有“证据”,符合逻辑的分析、看法~
文章会第一时间更新在GitHub,觉得写得还不错的,可以点个star支持下作者🍪
参考:
The text was updated successfully, but these errors were encountered: