javascript 的函数柯里化
概念
柯里化(currying),又称为部分求值,一个柯里化函数首先会接受一些参数,但是不会立即参与求值,而是将其保存在闭包中,并返回一个函数,在需要求值时,会将存在闭包中的变量拿出来求值。
在理解柯里化之前需要先理解闭包:闭包的简单理解.
举例
var currying = function(fn){
var args = [] // 1. 先提前声明了一个闭包变量,用来存储值
return function() { // 2. 返回出去一个闭包函数
if( arguments.length === 0){ // 3. 当没有传参时,把执行 cost 函数,并将 args 闭包变量传入
return fn.apply(this , args)
}else {
[].push.call(args, arguments) // 4. 有参数时,把参数 push 到 args 闭包变量中
return argument.callee
}
}
}
var cost = (function(){
var money = 0 // 闭包变量,存放值的和
return function(){
for(let i=0; i<arguments.length;i++ ){
money += arguments[i]
}
return money
}
})()
var cost = currying(cost) // 将 cost 函数柯里化
cost( 1 ) // 未真正执行 cost 里的闭包函数
cost( 2 ) // 未真正执行 cost 里的闭包函数
cost( 3 ) // 未真正执行 cost 里的闭包函数
cost() // 求值计算 6
以上示例就是一个简单的柯里化思想,它做了几件事:
1. 声明了一个 currying 函数,内部 return 的函数会通过传入的参数判断它是否需要求值。
2. 把真正需要求值的代码分离成 cost 函数。
3. 调用 currying 将 cost 函数柯里化。
4. 调用 cost 。
反柯里化 (uncurrying)
柯里化是闭包需要真正执行的函数,而反柯里化则是扩大函数和对象所拥有的方法,在自身没有此方法时去借调不属于它的方法。
示例
var uncurrying = function(){
let _that = this
return function() {
var obj = Array.prototype.shift.call( arguments )
return _that.apply(obj , arguments)
}
}
var push = Array.prototype.push.uncurrying()
var obj = {
'0': 1,
'length': 1
}
push(obj , 2)
console.log(obj) // { '0': 1,'1': 2,'length': 1 }
简单来说,其实就是改变了 push 函数里this的指向,使得 push 的 this 指向了 obj ,让 obj 也扩展了 push 方法。
这里可能会有疑问,为什么 obj 可以用 push 添加属性?改天更新。