Explain the Curitization of JavaScript Functions in detail
Baidu Encyclopedia's Interpretation of Curitization: In computer science, Currying is a technique that converts 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. The technology was named by Christopher Strachey after logician Haskell Curry, although it was invented by Moses Schnfinkel and Gottlob Frege.
It is believed that few people can immediately understand what function coritization is after reading the above explanation. Generally speaking, the main purpose of function coritization is to reduce function parameters and privatize some fixed parameters. Here is a very simple code for calculating the area of a circle to illustrate the principle of function coritization.
//circle function, accepting radius r and PI
function circle(r,p){
//Calculate the area of a circle with radius r
var area=p*r*r;
return area;
}
/*
* The circle function is simplified by the function coritization, and the area can be calculated only by passing in the radius.
* In any case, PI will not change, so we will write it to death without the need for external calls to pass in.
*/
function curryCircle(r){
var p=3.14;
var area=p*r*r;
return area;
}
Maybe you think this code is very two, but this is the real face of the function coritization. Of course, the above code is only a very small example, the real world function Curitization will be a little more vicious than it, let's discuss a more general example. Assuming that Pi is not unique (for example, we have three kinds of pi), the PI in our formula for calculating the area of a circle will vary according to different scenarios. At this time, we can not write to death directly, but need to configure PI according to different environments:
//circle function, accepting radius r and PI
function circle(r,p){
//Calculate the area of a circle with radius r
var area=p*r*r;
return area;
}
//Coritization function for circle function
function curry(fn,p){
var finalMethod=function(r){
var result=fn(r,p);
return result;
}
return finalMethod;
}
//We have three different pi
var curryCircle1=curry(circle,1.14);
var curryCircle2=curry(circle,2.14);
var curryCircle3=curry(circle,3.14);
//Output: 4.56 8.56 12.56
console.log(curryCircle1(2),curryCircle2(2),curryCircle3(2));
As you can see, curry method encapsulates the most basic circle method, saves the set p parameter (pi) and returns a final method, so that when we finally call final method, we only need to pass in the parameter r (radius). With the help of the function coritization, we have three simplified methods for calculating the area of a circle. The functions shown above can only be used for calculating the area of a circle. This time, we will write a more general function of Curitization:
function curry(fn){
//The first parameter is the basic execution method, slice excision.
var args=Array.prototype.slice.call(arguments,1);
//Return anonymous functions directly
return function(){
//slice new parameter so that concat can be called
var innerArgs=Array.prototype.slice.call(arguments);
//Merge configuration parameters with new incoming parameters
var finalArgs=args.concat(innerArgs);
return fn.apply(null,finalArgs);
};
}
The main work of curry () function is to sort the parameters of the returned function. The first parameter of Curry () is the function to be coritized, and the other parameter is the value to be passed in. To get all the parameters after the first parameter, the slice() method is called on the arguments object, and parameter 1 is passed in to indicate that the returned array contains all the parameters starting from the second parameter. The args array then contains parameters from external functions. In the internal function, an innerArgs array is created to hold all the incoming parameters (again slice()). Once you have an array of parameters from external and internal functions, you can use concat() to merge them into final Args. Finally, apply() is used to pass the result to the function. In this way, a general function coritization is realized. If the reader who has more power to do so can continue to look down, we will introduce the function coritization used in jQuery.
When we do coritization for a method, we don't even need to pass in fn to tell coritization to wrap our function. We can bind the function and coritization directly by prototype:
Function.prototype.curry=function(){
//Using the convenience of prototypes, we can refer to methods directly through this
var fn=this;
var args=Array.prototype.slice.call(arguments);
return function(){
var arg=0;
//Loop checks for differences between previously and newly passed parameters
for(var i=0;i<args.length && arg<arguments.length;i++){
if(args[i]===undefined){
args[i]=arguments[arg++];
}
}
return fn.apply(this,args);
};
};
Unlike before, we get method references through this reference so that when we need to coritize a function, we can simply write as follows:
var delay=setTimeout.curry(undefined,10);
delay is a setTimeout function that has been set 10 milliseconds in advance. We still save the parameter configuration through args, but this time it's a little different: the difference between args and arguments is checked inside the for loop to determine the parameter splicing. So the parameter passed to curry must be the full parameter (that is, the value that is not passed to undefined). Finally, we implement a coritization method that does not need to be introduced into fn.