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
varfn=function(){};varval=1;if(Object.prototype.toString.call(fn)=='[object Function]'){console.log(`${fn} is function.`);}if(Object.prototype.toString.call(val)=='[object Number]'){console.log(`${val} is number.`);}
上述代码,用反柯里化,可以这么写:
varfn=function(){};varval=1;vartoString=Object.prototype.toString.unCurrying();if(toString(fn)=='[object Function]'){console.log(`${fn} is function.`);}if(toString(val)=='[object Number]'){console.log(`${val} is number.`);}
前言
一、柯里化
1.1 例子
实现
add(1)(2, 3)(4)() = 10
的效果完整代码如下:
1.2 记忆传入参数
由于是延迟计算结果,所以要对参数进行记忆。
这里的实现方式是采用闭包。
当执行
var add = currying(...)
时,add
变量已经指向了next
方法。此时,allArgs
在next
方法内部有引用到,所以不能被GC回收。也就是说,allArgs
在该赋值语句执行后,一直存在,形成了闭包。依靠这个特性,只要把接收的参数,不断放入
allArgs
变量进行存储即可。所以,当
arguments.length > 0
时,就可以将接收的新参数,放到allArgs
中。最后返回
next
函数指针,形成链式调用。1.3 判断触发函数执行条件
题意是,空参数时,输出结果。所以,只要判断
arguments.length == 0
即可执行。另外,由于计算结果的方法,是作为参数传入
currying
函数,所以要利用apply
进行执行。综合上述思考,就可以得到以下完整的柯里化函数。
1.4 总结
柯里化,在这个例子中可以看出很明显的行为规范:
1.5 扩展
实现
add(1)(2, 3)(4)(5) = 15
的效果。很多人这里就犯嘀咕了:我怎么知道执行的时机?
其实,这里有个忍者技艺:
valueOf
和toString
。js在获取当前变量值的时候,会根据语境,隐式调用
valueOf
和toString
方法进行获取需要的值。那么,实现起来就很简单了。
二、反柯里化
2.1 例子
有以下轻提示类。现在想要单独使用其
show
方法,输出新对象obj
中的内容。用反柯里化的方式,可以这么做
2.2 反柯里化的行为
在上面的例子中,
Toast.prototype.show
方法,本来是Toast
类的私有方法。跟新对象obj
没有半毛钱关系。经过反柯里化后,却可以为
obj
对象所用。为什么能被
obj
所用,是因为内部将Toast.prototype.show
的上下文重新定义为obj
。也就是用apply
改变了this
指向。而实现这一步骤的过程,就需要增加反柯里化后的
objShow
方法参数。2.3 另一种反柯里化的实现
这里的难点,在于理解
Function.prototype.call.apply(self, arguments);
。可以分拆为两步:
1)
Function.prototype.call.apply(...)
的解析可以看成是
callFunction.apply(...)
。这样,就清晰很多。callFunction
的this
指针,被apply
修改为self
。然后执行
callFunction
->callFunction(arguments)
2)
callFunction(arguments)
的解析call
方法,第一个参数,是用来指定this
的。所以callFunction(arguments)
->callFunction(arguments[0], arguments[1-n])
。由此可以得出,反柯里化后,第一个参数,是用来指定
this
指向的。3)为什么要用apply(self, arguments)
如果使用
apply(null, arguments)
,因为null
对象没有call
方法,会报错。三、实战
3.1 判断变量类型(反柯里化)
上述代码,用反柯里化,可以这么写:
3.2 监听事件(柯里化)
使用柯里化,优化监听DOM节点事件。
addEventListener
三个参数不用每次都写。后记
其实,反柯里化和泛型方法一样,只是理念上有一些不同而已。理解这种思维即可。
The text was updated successfully, but these errors were encountered: