This article brings you relevant knowledge about javascript, which mainly introduces the related issues of function currying in JavaScript. Currying is to transform a function that accepts multiple parameters. It is a technique that accepts a single parameter and returns a new function that accepts the remaining parameters and returns the result. I hope it will be helpful to everyone.
Related recommendations: javascript tutorial
apply(context,[arguments])
,call(context,param1,param2,...)
. Currying is to transform a function that accepts multiple parameters into a function that accepts a single parameter (the first parameter of the original function), and returns a new function that accepts the remaining parameters and returns the result. Technology.
For example, there is a add()
function, which is a function used to process the addition and sum of the parameters (param1, params2,...) we pass to it. .
// 在这里第一个具有两个参数`x`、`y`的`add(x , y)`函数 function add(x , y){ return x + y; } // 调用`add()`函数,并给定两个参数`4`和`6` add(4,6); // 模拟计算机操作,第一步 传入第一个参数 4 function add(4 , y){ return 4 + y; } // 模拟计算机操作,第二步 传入第一个参数 6 function add(4 , 6){ return 4 + 6; }
What would it look like if we curried the add()
function? Here is a simple implementation:
// 柯里化过的add()函数,可以接受部分参数 function add(x ,y){ if (typeof y === 'undefined') { return function (newy){ return x + newy; } } // 完整应用 return x + y; } // 测试调用 console.log(typeof add(4)); // [Function] console.log(add(4)(6)); // 10 // 可以创建保存函数 let saveAdd = add(4); console.log(saveAdd(6)); // 10
As can be seen from the above simple curried add()
function, the function can accept some functions and then return a new function to make it Continue with the remaining functions.
Here we create a public curried function, so that we don’t have to implement complex functions internally every time we write a function The currying process.
// 定义一个createCurry的函数function createCurry(fn){ var slice = Array.prototype.slice, stored_args = slice.call(arguments,1); return function () { let new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null,args); }}
In the above public curried function:
arguments
, is not a real array, just an array with length
Attribute object, so we borrow the slice
method from Array.prototype
to help us convert arguments
into a real array to facilitate our better operations . createCurry
for the first time, the variable stored_args
holds the parameters except the first parameter, because the first parameter is We need curried functions. createCurry
function, the variable new_args
gets the parameters and converts them into an array. stored_args
through a closure and the value of the variable new_args
is combined into a new array and assigned to the variable args
. fn.apply(null,args)
method to execute the curried function. Now let’s test the public currying function
// 普通函数add() function add(x , y){ return x + y; } // 柯里化得到一个新的函数 var newAdd = createCurry(add,4); console.log(newAdd(6)); // 10 //另一种简便方式 console.log(createCurry(add,4)(6));// 10
Of course, this is not limited to currying of two parameters, but can also be multiple Parameters:
// 多个参数的普通函数 function add(a,b,c,d){ return a + b + c + d; } // 柯里化函数得到新函数,多个参数可以随意分割 console.log(createCurry(add,4,5)(5,6)); // 20 // 两步柯里化 let add_one = createCurry(add,5); console.log(add_one(5,5,5));// 20 let add_two = createCurry(add_one,4,6); console.log(add_two(6)); // 21
Through the above example, we can find a limitation, that is, whether it is two parameters or multiple parameters, it can only be executed in two steps, such as the following formula:
If we want to be more flexible:
How do we achieve it?
After the above exercises, we found that the curried function we created has certain limitations. We hope that the function can be executed in multiple steps:
// 创建一个可以多步执行的柯里化函数,当参数满足数量时就去执行它: // 函数公式:fn(x,y,z,w) ==> fn(x)(y)(z)(w); let createCurry = (fn,...params)=> { let args = parsms || []; let fnLen = fn.length; // 指定柯里化函数的参数长度 return (...res)=> { // 通过作用域链获取上一次的所有参数 let allArgs = args.slice(0); // 深度拷贝闭包共用的args参数,避免后续操作影响(引用类型) allArgs.push(...res); if(allArgs.length < fnLen){ // 当参数数量小于原函数的参数长度时,递归调用createCurry函数 return createCurry.call(this,fn,...allArgs); }else{ // 当参数数量满足时,触发函数执行 return fn.apply(this,allArgs); } } } // 多个参数的普通函数 function add(a,b,c,d){ return a + b + c + d; } // 测试柯里化函数 let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); // 10
We have implemented a flexible currying function above, but here we find another problem:
curryAdd(add,1,2,3,4)()
;add()
function. This is also a way; but since we are here to meet the number of parameters, we still deal with this situation. Here we only need to make a judgment before returning the function:
let createCurry = (fn,...params)=> { let args = parsms || []; let fnLen = fn.length; // 指定柯里化函数的参数长度 if(length === _args.length){ // 加入判断,如果第一次参数数量以经足够时就直接调用函数获取结果 return fn.apply(this,args); } return (...res)=> { let allArgs = args.slice(0); allArgs.push(...res); if(allArgs.length < fnLen){ return createCurry.call(this,fn,...allArgs); }else{ return fn.apply(this,allArgs); } }}
The above can be regarded as completing a flexible currying function, but there is not yet The calculation is very flexible because we cannot control when it is executed. It will be executed automatically as long as the number of parameters is sufficient. What should we do if we want to achieve a timing that can control its execution?
Let’s directly explain the function formula here:
// 当参数满足,再次执行时调用函数 let createCurry = (fn,...params)=> { let args = parsms || []; let fnLen = fn.length; // 指定柯里化函数的参数长度 //当然这里的判断需要注释掉,不然当它第一次参数数量足够时就直接执行结果了 //if(length === _args.length){ // 加入判断,如果第一次参数数量以经足够时就直接调用函数获取结果 //return fn.apply(this,args); //} return (...res)=> { let allArgs = args.slice(0); allArgs.push(...res); // 在这里判断输入的参数是否大于0,如果大于0在判断参数数量是否足够, // 这里不能用 && ,如果用&& 也是参数数量足够时就执行结果了。 if(res.length > 0 || allArgs.length < fnLen){ return createCurry.call(this,fn,...allArgs); }else{ return fn.apply(this,allArgs); } } } // 多个参数的普通函数 function add(a,b,c,d){ return a + b + c + d; } // 测试可控制的柯里化函数 let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); // function console.log(curryAdd(2)(3)(4)()); // 10 console.log(curryAdd(2)(3)()); // 当参数不足够时返回 NaN
相关推荐:javascript学习教程
The above is the detailed content of Let's talk about JavaScript function currying. For more information, please follow other related articles on the PHP Chinese website!