Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to master the high-order function technology

2025-02-03 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces "how to master high-order function technology". In daily operation, I believe that many people have doubts about how to master high-order function technology. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubt of "how to master high-order function technology"! Next, please follow the editor to study!

I. higher-order functions

In mathematics and computer science, higher-order functions are functions that satisfy at least one of the following conditions:

Accept one or more functions as input

Output a function.

Receives one or more functions as input, that is, the function is passed as an argument. I believe many people will be familiar with this kind of application scenario. For example, the commonly used Array.prototype.map () and Array.prototype.filter () higher-order functions:

/ / Array.prototype.map higher order function const array = [1,2,3,4]; const map = array.map (x = > x * 2); / / [2,4,6,8] / / Array.prototype.filter higher order function const words = ['semlinker',' kakuqo', 'lolo',' abao']; const result = words.filter (word = > word.length > 5); / / ["semlinker", "kakuqo"]

The output of a function, that is, after calling a higher-order function, will return a new function. In our daily work, the common debounce and throttle functions satisfy this condition, so they can also be called higher-order functions.

Second, function combination

Function combination is the process of combining two or more functions to form a new function:

Const compose = function (f, g) {return function (x) {return f (g (x));};}

In the above code, f and g are functions, and x is the parameter that combines to generate the new function.

2.1 the role of function combination

In the process of project development, in order to realize the reuse of functions, we usually try our best to ensure that the responsibilities of functions are single. For example, we define the following functions:

On the basis of the above functions, we are free to combine the functions to achieve specific functions:

Function lowerCase (input) {return input & & typeof input = = "string"? Input.toLowerCase (): input;} function upperCase (input) {return input & & typeof input = = "string"? Input.toUpperCase (): input;} function trim (input) {return typeof input = = "string"? Input.trim (): input;} function split (input, delimiter = ",") {return typeof input = = "string"? Input.split (delimiter): input;} const trimLowerCaseAndSplit = compose (trim, lowerCase, split); trimLowerCaseAndSplit ("a", "b", "c"]

In the above code, we implement a trimLowerCaseAndSplit function through the compose function, which first performs blanking processing on the input string, then converts the letters contained in the string to lowercase, and finally uses the semicolon to split the string. Using the technology of function combination, we can easily implement a trimUpperCaseAndSplit function.

2.2 implementation of combinatorial functions

Function compose (... funcs) {return function (x) {return funcs.reduce (function (arg, fn) {return fn (arg);}, x);};}

In the above code, we use the Array.prototype.reduce method to schedule the composite function, and the corresponding execution order is from left to right. This execution order is consistent with the execution order of Linux pipes or filters.

However, if you want to start from right to left, you can use the Array.prototype.reduceRight method to do so.

In fact, whenever I see the compose function, Brother Po can't help thinking about the compose function introduced in the article "how to better understand Middleware and Onion Model":

Function compose (middleware) {/ / omit some codes return function (context, next) {let index =-1; return dispatch (0); function dispatch (I) {if (I [1, 2, 3] curried (1, 2) (3); / = > [1, 2, 3] curried (1, 2, 3); / / > [1, 2, 3]

_ .curry (func, [arity=func.length])

Create a function that takes parameters from func, or calls the results returned by func, or directly returns the results executed by func if the parameters required by func have been provided. Or return a function that accepts the remaining func parameters. You can use func.length to set the number of parameters to accumulate.

Source: https://www.lodashjs.com/docs/lodash.curry

It should be noted that in mathematics and theoretical computer science, only one parameter can be passed at a time. For JavaScript language, the Corialization function in practical application can pass one or more parameters. OK, after introducing the relevant knowledge of Coriarization, let's introduce the function of Corification.

3.1 the role of Corey

3.1.1 Parameter reuse

Function buildUri (scheme, domain, path) {return `${scheme}: / / ${domain} / ${path}`;} const profilePath = buildUri ("https", "github.com", "semlinker/semlinker"); const awesomeTsPath = buildUri ("https", "github.com", "semlinker/awesome-typescript")

In the above code, we first define a buildUri function that can be used to build uri addresses. Then we use the buildUri function to build the Github home page of Brother Po and the address of the awesome-typescript project. For the above uri address, we find that the values of the two parameters https and github.com are the same.

If we need to continue to build the addresses of Po's other projects, we need to set the same parameter values repeatedly. So is there any way to simplify the process? The answer is yes, it is to perform Corey processing on the buildUri function, as follows:

Const _ = require ("lodash"); const buildUriCurry = _ .curry (buildUri); const myGithubPath = buildUriCurry ("https", "github.com"); const profilePath = myGithubPath ("semlinker/semlinker"); const awesomeTsPath = myGithubPath ("semlinker/awesome-typescript")

3.1.2 delayed calculation / operation

Const add = function (a, b) {return a + b;}; const curried = _ .curry (add); const plusOne = curried (1)

In the above code, we can implement the delay calculation by performing the "Corialization" processing on the add function. OK, after a brief introduction to the role of Corialization, let's implement a Corialization function.

3.2 realization of Coriarization

Now we know that when the Corey function receives enough arguments, it starts to execute the original function. If the parameters received are insufficient, a new function is returned to receive the remaining parameters. Based on the above characteristics, we can implement a curry function ourselves:

Function curry (func) {return function curried (... args) {if (args.length > = func.length) {/ / get the number of formal parameters of the function return func.apply (this, args) through the function's length attribute;} else {return function (... args2) {return curried.apply (this, args.concat (args2));};}

IV. Application of partial function

In computer science, partial function application (Partial Application) refers to a function that fixed some parameters of a function and then produced another smaller element. The so-called element refers to the number of function parameters, for example, a function with one parameter is called a unary function.

Partial function applications (Partial Application) can easily be confused with function Corialization. The differences between them are:

A partial function application is to fix one or more parameters of a function and return a function that can receive the remaining parameters.

Corialization converts a function into multiple nested unary functions, that is, each function receives only one parameter.

Now that we know the difference between a partial function and a Cori function, let's use the partial function provided by Lodash to see how it works.

4.1 use of partial functions

Function buildUri (scheme, domain, path) {return `${scheme}: / / ${domain} / ${path}`;} const myGithubPath = _ .partial (buildUri, "https", "github.com"); const profilePath = myGithubPath ("semlinker/semlinker"); const awesomeTsPath = myGithubPath ("semlinker/awesome-typescript")

_ .partial (func, [partials])

Create a function. This function calls func, passing in the preset partials parameter.

4.2 realization of partial function

Partial functions are used to fix one or more parameters of a function and return a function that can receive the remaining parameters. Based on the above characteristics, we can implement a partial function ourselves:

Function partial (fn) {let args = [] .slice.call (arguments, 1); return function () {const newArgs = args.concat ([] .slice.call (arguments)); return fn.apply (this, newArgs);};}

4. 3 partial function implementation of vs Corey

5. Inert function

Due to some compatibility problems between different browsers, we need to make judgments when using some Web API, such as:

Function addHandler (element, type, handler) {if (element.addEventListener) {element.addEventListener (type, handler, false);} else if (element.attachEvent) {element.attachEvent ("on" + type, handler);} else {element ["on" + type] = handler;}

In the above code, we implement the handling of adding event listeners to different browsers. The code is also simple to implement, but there is a problem, that is, it needs to be judged every time it is called, which is obviously unreasonable. For the above problem, we can solve it by lazily loading functions.

5.1 lazily loading function

The so-called lazy loading is that when the function is executed according to the condition for the first time, when the function is called for the second time, the condition is no longer detected and the function is executed directly. To achieve this function, we can overwrite the called function in the branch that meets the judgment condition for the first time, as shown below:

Function addHandler (element, type, handler) {if (element.addEventListener) {addHandler = function (element, type, handler) {element.addEventListener (type, handler, false);} else if (element.attachEvent) {addHandler = function (element, type, handler) {element.attachEvent ("on" + type, handler);} } else {addHandler = function (element, type, handler) {element ["on" + type] = handler;};} / / ensure that the listening return addHandler (element, type, handler) can be executed normally in the first call;}

In addition to using the above methods, we can also use self-executing functions to achieve lazy loading:

Const addHandler = (function () {if (document.addEventListener) {return function (element, type, handler) {element.addEventListener (type, handler, false);};} else if (document.attachEvent) {return function (element, type, handler) {element.attachEvent ("on" + type, handler);};} else {return function (element, type, handler) {element ["on" + type] = handler ) ()

Through the self-executing function, a condition judgment is performed during the code loading phase, and then a new function is returned in the corresponding condition branch to implement the corresponding processing logic.

VI. Cache function

The caching function caches the calculation results of the function, and the next time the function is called with the same parameters, the cached results are returned directly without the need to execute the function again. This is a common performance optimization method of exchanging space for time.

To implement the caching function, we can take the serialized parameters as key and store the result of the first call in the object as value. Before each function call, determine whether the cache contains the corresponding key, and if so, directly return the corresponding value of the key. After analyzing the implementation of the cache function, let's take a look at how to implement it:

Function memorize (fn) {const cache = Object.create (null); / / object return function (... args) {const _ args = JSON.stringify (args); return cache [_ args] | | (cache [_ args] = fn.apply (fn, args));};}

After defining the memorize cache function, we can use it like this:

Let complexCalc = (a, b) = > {/ / perform complex calculations}; let memoCalc = memorize (complexCalc); memoCalc (666,888); memoCalc (666,888); / / get this from the cache, the study on "how to master high-order functional techniques" is over, hoping to solve everyone's doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report