JS函数柯里化
提前接收部分参数,延迟执行,不立即输出结果,而是返回一个接受剩余参数的函数
EXAMPLE 01
"use strict";
/**
*
* EXAMPLE 0-1
*/
;(() => {
function add_currying() {
console.log(arguments, this);
}
function currying(fn) {
let cache = []
let next = function () {
if (arguments.length > 0) {
let args = [].slice.call(arguments, 0)
cache = cache.concat(args)
return next
} else {
return fn.apply(this, cache) // 看到结果后,明白这里的this是没有用的,可以传null
}
}
next.empty = function () {
let res = fn.apply(this, cache)
cache = []
return res
}
return next
}
var add = currying(add_currying)
add(1)(2)(3, 4).empty()
//[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 } { [Function: next] empty: [Function] }
add(2)(5)(7)()
//[Arguments] { '0': 2, '1': 5, '2': 7 } undefined
})()
复制代码
EXAMPLE 02
/**
*
* EXAMPLE 0-2
*/
;( () => {
function add_currying () {
console.log(arguments,this);// [Arguments] { '0': 1, '1': 1, '2': 34, '3': 5 } null
return 1
}
function currying(fn){
let cache = []
let next = function(){
cache = [...cache,...arguments]
return next
}
next.toString = next.valueOf = () => fn.apply(null,cache)
return next
}
var add = currying(add_currying)
console.log(add(1)(1,34,5) + 1); //2
})()
复制代码
反柯里化
Function.prototype.unCurrying = function(){
let self = this
return function(){
return Function.prototype.call.apply(self,arguments)
}
}
var show = Object.prototype.toString.unCurrying()
console.log(show('23'));
复制代码
如何理解 Function.prototype.call.apply
var show = Object.prototype.toString.unCurrying() // ==>
Function.prototype.unCurrying = function(){
let self = this // this ==> Object.prototype.toString
return function(){
return Function.prototype.call.apply(self,arguments)
// ==> Object.prototype.toString.call(arguments)
// 这里call的this指向被apply方法转变为Object.prototype.toString
// 同时执行 toString 并且将toString的this指向转变为 arguments[0]
// 最终执行的是 arguments[0].toString
}
}
// 该方式本质上就是将原来必须由对象去点方法的形式改为,方法接受对象作为参数
复制代码
其实这与下面的方法没什么不同
var unCurrying = function(fn){
return function(){
return fn.apply(arguments[0],[].slice.call(arguments,1))
}
}
var show2 = unCurrying(Object.prototype.toString)
console.log(show2('23'));
复制代码
写了一通,发现反柯里化好像没什么道理(小声BB),不能让大佬发现我的无知。
柯里化应用
/**
* 柯里化应用
* @descript 缓存计算值,重复计算(需要目标值)
*/
;
(() => {
function currying(v, fn) {
let cache = v
let next = function () {
if (arguments.length > 0) {
let args = [].slice.call(arguments, 0)
cache = fn.call(this, cache, ...arguments)
return next
} else {
let res = cache
cache = v
return res
}
}
next.empty = function () {
let res = cache
cache = v
return res
}
return next
}
function ab_currying(a, b) {
return a + b
}
var ab = currying(0, ab_currying)
console.log(ab(1)(2)(3)()); //6
console.log(ab(4,5)(9)()); // 13
})()
复制代码
/**
* 给定目标值,分别计算
*/
;
(() => {
Function.prototype.currying = function () {
let fn = this,
args = arguments
return function () {
return fn.apply(this, [...args, ...arguments])
}
}
function ab(a, b) {
return a + b
}
let test = ab.currying(1)
console.log(test(2)); // 3
console.log(test(3)); // 4
})()
复制代码
/**
* 简化参数
* @descript 当函数参数中有多个同样的参数
*/
;
(() => {
Function.prototype.currying = function () {
let fn = this,
args = arguments
return function () {
let index = 0,
len = arguments.length,
new_args = [...args]
for (let i = 0, args_len = args.length; i < args_len && len < args_len; i++) {
if (args[i] === undefined) {
new_args[i] = arguments[index++]
}
}
return fn.apply(this, new_args)
}
}
function test_currying(a, b, c) {
console.log(a, b, c);
}
let test = test_currying.currying(1, undefined, 2)
test(10) // 1 10 2
test(100) // 1 100 2
/*
let bindClick = document.body.addEventListner.currying('click',undefined,false)
bindClick(function(){
console.log(1)
})
bindClick(function(){
console.log(2)
})
*/
})()
复制代码