柯里化

# 柯里化

# 定义

在数学和计算机科学中,柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。

# 用途

主要有三个:

  • 参数复用

  • 提前返回

  • 延迟调用

比如封装了一个请求函数,传入三个参数URL,方法,数据。

假设每次我们都请求同一个URL,但是每次调用都需要传URL,那么我们可以使用柯里化来返回传入URL之后的函数,以后调用该函数就只需要传入方法和数据即可,这就是参数复用。

function uri_curring(protocol) {
  return function(hostname, pathname) {
    return `${protocol}${hostname}${pathname}`; 
  }
}

// 测试一下
const uri_https = uri_curring('https://');

const uri1 = uri_https('www.fedbook.cn', '/frontend-languages/javascript/function-currying/');
const uri2 = uri_https('www.fedbook.cn', '/handwritten/javascript/10-实现bind方法/');
const uri3 = uri_https('www.wenyuanblog.com', '/');

console.log(uri1);
console.log(uri2);
console.log(uri3);

# 封装curry函数

需求:

  • 封装一个curry()函数

  • 接收一个参数,该参数是一个要柯里化的函数

  • 返回一个函数

# 1.第一版

第一版先实现一个curry(fn,...),即可以传入函数外的其他参数。

函数参数不定长,通过arguments获取,由于它是一个类数组,要使用Array的方法需要借助call。

function curry(fn){
    var args = [].slice.call(arguments , 1)    // 获取第一个参数之后的参数数组
    // 返回一个函数
    return function(){
        var newArgs = args.concat([].slice.call(arguments))
        return fn.apply(this , newArgs)
    }
}

调用方式

function add(a, b) {
    return a + b;
}

var addCurry = curry(add, 1, 2);
addCurry() // 3
//或者
var addCurry = curry(add, 1);
addCurry(2) // 3
//或者
var addCurry = curry(add);
addCurry(1, 2) // 3

# 2.第二版

需求:

  • 实现一个curry函数,可以这样调用:curry(fn[,length])

  • 返回一个函数,函数可以接收任意多个参数执行。

// 传入一个函数
// 返回一个柯里化后的函数
function curry(fn, len) {
	len = len || fn.length // 2
	return function () {
    // 传入参数个数少于需要个数则保存参数
		if (arguments.length < len) {
			var args = [].slice.call(arguments) // 保存参数
			var f = function () {
				return fn.apply(this, args.concat([].slice.call(arguments)))
			}
			return curry(f, len - arguments.length)
		} else {
			return fn.apply(this, arguments)
		}
	}
}

const add = curry(function (a, b, c) {
	return a + b + c
})
console.log(add(1, 2, 3))
console.log(add(1)(2, 3))
console.log(add(1)(2)(3))