Coriolization of JavaScript function
- 2021-12-04 18:00:54
- OfStack
1 What is Currization of Functions
In computer science, Currification (
Currying
) is the technique of transforming a function that accepts multiple parameters into a function that accepts a single 1 parameter (the first parameter of the original function) and returns a new function that accepts the remaining parameters and returns the result
Haskell Curry
Named.
What do you mean? Simply put, Currization is a technique used to transform multi-parameter functions.
For example:
// This is 1 Acceptance 3 A function with three parameters
const add = function(x, y, z) {
return x + y + z
}
If we transform it by 1, we can get such a function:
// Receive 1 Single order 1 Parameter
const curryingAdd = function(x) {
// And returns the function that accepts the remaining arguments
return function(y, z) {
return x + y + z
}
}
What difference does this make? Compare from the call:
// Call add
add(1, 2, 3)
// Call curryingAdd
curryingAdd(1)(2, 3)
// See more clearly 1 Point, equivalent to the following
const fn = curryingAdd(1)
fn(2, 3)
As you can see, the transformed function can accept parameters in batches. Remember this point first, which will be useful below. Even fn (
curryingAdd
The function returned) can also continue to transform
As follows:
const curryingAdd = function(x) {
return function(y) {
return function(z) {
return x + y + z
}
}
}
// Call
curryingAdd(1)(2)(3)
// I.e.
const fn = curryingAdd(1)
const fn1 = fn(2)
fn1(3)
The above two transformations are the Curritization of functions.
Simply put, it is to put a multi-parameter function
f
Transformed into a function that accepts some parameters
g
And this function
g
Returns 1 function
h
The function h is used to accept other parameters. The function h can continue Currization. It is the process of a doll ~
So what's the use of going to so much trouble to Corrigenize the function?
The function and characteristics of Corrigenization
2.1 Parameter multiplexing
Requirements encountered in work: Check whether the telephone number, email address and ID card are legal through regularity, etc.
So we encapsulate a check function as follows:
/**
* @description Verify the string through regularity
* @param {RegExp} regExp Regular object
* @param {String} str String to be verified
* @return {Boolean} Whether it passes the verification
*/
function checkByRegExp(regExp, str) {
return regExp.test(str)
}
If we want to check a lot of mobile phone numbers and mailboxes, we will call like this:
// Check the mobile phone number
checkByRegExp(/^1\d{10}$/, '15152525634');
checkByRegExp(/^1\d{10}$/, '13456574566');
checkByRegExp(/^1\d{10}$/, '18123787385');
// Verify mailbox
checkByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, 'fsds@163.com');
checkByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, 'fdsf@qq.com');
checkByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, 'fjks@qq.com');
It seems that there is no problem, but in fact there is still room for improvement
When checking the data of the same type 1, we write the same regularity many times. The code is poorly readable. If there is no comment, we can't see the effect of regularity in one timeWe try to use functional Curritization to improve:
// Curritization of a function
function checkByRegExp(regExp) {
return function(str) {
return regExp.test(str)
}
}
So we pass in different regular objects, and we can get functions with different functions:
// Check mobile phone
const checkPhone = curryingCheckByRegExp(/^1\d{10}$/)
// Verify mailbox
const checkEmail = curryingCheckByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/)
Now it is easier to check the code of mobile phone and email, and the readability is enhanced
// Check the mobile phone number
checkPhone('15152525634');
checkPhone('13456574566');
checkPhone('18123787385');
// Verify mailbox
checkEmail('fsds@163.com');
checkEmail('fdsf@qq.com');
checkEmail('fjks@qq.com');
This is parameter reuse: we just need to put the first parameter
regExp
Reuse, you can directly call functions with specific functions
Generic functions such as
checkByRegExp
) solves the compatibility problem, but it also brings inconvenience to use, for example, different application scenarios need to pass multiple different parameters to solve the problem
Sometimes the same rule may be used repeatedly (such as checking the parameters of mobile phones), which leads to code repetition. Currization can eliminate repetition and achieve the purpose of reusing parameters.
An important thought of Corrigendum: reducing the scope of application and improving the applicability
2.2 Early return
In
JS DOM
In the event listener, we use
Haskell Curry
0
Method to add an event handler to the element, but some browser versions do not support this method, we will use the
attachEvent
Method to replace.
At this time, we will write a code compatible with each browser version:
/**
* @description:
* @param {object} element DOM Element object
* @param {string} type Event type
* @param {Function} fn Event handler
* @param {boolean} isCapture Capture or not
* @return {void}
*/
function addEvent(element, type, fn, isCapture) {
if (window.addEventListener) {
element.addEventListener(type, fn, isCapture)
} else if (window.attachEvent) {
element.attachEvent("on" + type, fn)
}
}
We use
addEvent
To add event listening, but every time this method is called, a judgment will be made. In fact, after the browser version is determined, there is no need to repeat the judgment.
Currification treatment:
// Receive 1 Single order 1 Parameter
const curryingAdd = function(x) {
// And returns the function that accepts the remaining arguments
return function(y, z) {
return x + y + z
}
}
0
What we get now
addEvent
It is a function obtained after judgment, so there is no need to repeat judgment when calling it later.
This is to return in advance or confirm in advance. After curitization, functions can handle some tasks in advance and return 1 function to handle other tasks
In addition, we can see that,
curryingAddEvent
It seems that the parameters are not accepted. This is because of the condition of the primitive function (that is, whether the browser version supports it or not
Haskell Curry
0
) is obtained directly from the global.
Logically, it can actually be changed to:
// Receive 1 Single order 1 Parameter
const curryingAdd = function(x) {
// And returns the function that accepts the remaining arguments
return function(y, z) {
return x + y + z
}
}
1
Of course there is no need to change this ~
2.3 Delayed execution
In fact, the above example of regular checksum event listening already reflects the delayed execution.
curryingCheckByRegExp
After the function is called, it returns
checkPhone
And
checkEmail
Function
curringAddEvent
After the function is called, it returns
addEvent
Function
None of the returned functions will be executed immediately, but will wait for the call.
3 Encapsulate the Universal Currization Tool Function #
Above, we modified the original function manually by Curritization of the function, which will
add
Changed to
curryingAdd
, will
checkByRegExp
Changed to
curryingCheckByRegExp
, will
addEvent
Changed to
curryingAddEvent
.
Do we have to manually modify the underlying function every time we Curritization the function? Of course not
We can encapsulate a general Coriolian tool function (interview handwritten code)
// Receive 1 Single order 1 Parameter
const curryingAdd = function(x) {
// And returns the function that accepts the remaining arguments
return function(y, z) {
return x + y + z
}
}
2
This Currization tool function is used to receive some parameters, then returns a new function waiting to receive the remaining parameters, recursively until all the required parameters are received, and then passes
apply
Call the original function.
Now we basically don't have to modify the original function manually to Currize the function
// Directly use the tool function to return the function to check the mobile phone and mailbox
const checkPhone = currying(checkByRegExp(/^1\d{10}$/))
const checkEmail = currying(checkByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/))
However, the above example of event monitoring can't be Corrified by this tool function. As mentioned earlier, because its conditions are directly obtained from the global situation, it is quite special. If the conditions are passed in from the outside, it can be Corrified by the tool function. Of course, this is not necessary. It is more direct and readable to modify the original function directly