In-depth analysis of currying functions in JavaScript

Source: Internet
Author: User
The following small series will bring you an in-depth analysis of the JavaScript function currying Keri. I think this is quite good. I will share it with you and give you a reference, let's take a look at the source of curry and the name of the mathematician Haskell Curry (the programming language Haskell is also named after him ).

Curialization is also called partial evaluation. It means to pass parameters to the function step by step. After each parameter is passed, some parameters are applied and a more specific function is returned to accept the remaining parameters, in the middle, multiple layers can be nested to accept some parameter functions until the final result is returned.

Therefore, the process of curialization is to gradually transfer parameters, gradually narrow the applicability of the function, and gradually solve the problem.

Ke Lihua a summation Function
Perform step-by-step evaluation. Let's look at a simple example.

var concat3Words = function (a, b, c) {   return a+b+c; };  var concat3WordsCurrying = function(a) {   return function (b) {     return function (c) {       return a+b+c;     };   }; }; console.log(concat3Words("foo ","bar ","baza"));      // foo bar baza console.log(concat3WordsCurrying("foo "));         // [Function] console.log(concat3WordsCurrying("foo ")("bar ")("baza")); // foo bar baza 

As you can see, concat3WordsCurrying ("foo") is a Function. Each call returns a new Function, which accepts another call and returns a new Function, until the final result is returned, the distribution is solved, and the process is progressive. (PS: the closure feature is used here)

Now let's go further. If more than three parameters can be passed, we can pass any number of parameters. When no parameter is passed, what is the output result?

First, let's make a general implementation:

var add = function(items){   return items.reduce(function(a,b){     return a+b   }); }; console.log(add([1,2,3,4])); 

However, if you want to multiply each number by 10 and then add it, then:

var add = function (items,multi) {   return items.map(function (item) {     return item*multi;   }).reduce(function (a, b) {     return a + b   }); }; console.log(add([1, 2, 3, 4],10)); 

Fortunately, there are map and reduce functions. If we want to add 1 to each item and then summarize it in this mode, we need to replace the functions in map.

Let's take a look at the implementation of colialization:

Var adder = function () {var _ args = []; return function () {if (arguments. length = 0) {return _ args. reduce (function (a, B) {return a + B;}) ;}[]. push. apply (_ args, []. slice. call (arguments); return arguments. callee ;}}; var sum = adder (); console. log (sum); // Function sum (100,200) (300); // flexible calling method. One or more parameters can be input for one call, and supports the chain call sum (400); console. log (sum (); // 1000 (sum calculation)

The above adder is a colized function, which returns a new function. The new function receives new parameters in batches and delays until the last computation.

General Keri Functions

The more typical Keri will encapsulate the last computation into a function, and then pass this function as a parameter to the Keri function, which is clear and flexible.

For example, if each item is multiplied by 10, we can pass the processing function as a parameter:

Var currying = function (fn) {var _ args = []; return function () {if (arguments. length = 0) {return fn. apply (this, _ args);} Array. prototype. push. apply (_ args, []. slice. call (arguments); return arguments. callee ;}; var multi = function () {var total = 0; for (var I = 0, c; c = arguments [I ++];) {total + = c ;}return total ;}; var sum = currying (multi); sum (100,200) (300); sum (400); console. log (sum (); // 1000 (calculated only when the call is blank)

In this way, sum = currying (multi) is clearly called, and the calling effect is brilliant. For example, to accumulate multiple values, you can use multiple values as the sum (, 3) parameter ), it can also support chained calls, sum (1) (2) (3)

Basis of colialization

The above code is actually a high-order function. A high-order function is a function that operates functions. It receives one or more functions as parameters and returns a new function. In addition, it depends on the closure feature to save the parameters entered in the intermediate process. That is:

Functions can be passed as parameters.
The function can be used as the return value of the function.
Closure
Ke Lihua's role
Latency calculation. The above example has been relatively low.

Parameter reuse. When the same function is called multiple times and the majority of parameters passed are the same, the function may be a good candidate for colialization.

Dynamically create a function. This can be because a new function is dynamically generated to process the subsequent business after partial calculation results, thus omitting repeated calculation. Alternatively, you can dynamically create a new function by applying a subset of parameters that will be passed in to the function, this new function saves the repeated input parameters (you do not have to upload them each time ). For example, the event browser can add an event by using the following auxiliary methods:

 var addEvent = function(el, type, fn, capture) {    if (window.addEventListener) {      el.addEventListener(type, function(e) {        fn.call(el, e);      }, capture);    } else if (window.attachEvent) {      el.attachEvent("on" + type, function(e) {        fn.call(el, e);      });    }  }; 

Execute the if... else ..., in fact, you only need to make one decision in a browser, and dynamically generate a new function based on the results after one decision, so you do not have to re-calculate it in the future.

var addEvent = (function(){   if (window.addEventListener) {     return function(el, sType, fn, capture) {       el.addEventListener(sType, function(e) {         fn.call(el, e);       }, (capture));     };   } else if (window.attachEvent) {     return function(el, sType, fn, capture) {       el.attachEvent("on" + sType, function(e) {         fn.call(el, e);       });     };   } })(); 

In this example, after the first if... else... judgment, some computation is completed, and a new function is dynamically created to process the parameters passed in later. This is a typical ke Lihua.

Function. prototype. bind method is also a Keri Application

Unlike the direct execution of the call/apply method, the bind method sets the first parameter as the context of the function execution, and transmits other parameters to the calling method in sequence (the main body of the function itself does not execute, can be regarded as delayed execution), and dynamic creation returns a new function, which conforms to the characteristics of colitization.

Var foo = {x: 888}; var bar = function () {console. log (this. x );}. bind (foo); // bind the bar (); // 888

The following is a simulation of a bind function. testBind creates and returns a new function. In the new function, the function that actually needs to execute the business is bound to the context passed in by the real parameter, and the execution is delayed.

Function. prototype. testBind = function (scope) {var fn = this; // this indicates a function that calls the testBind method, return function () {return fn. apply (scope) ;}}; var testBindBar = bar. testBind (foo); // bind foo to delay the execution of the console. log (testBindBar); // Function (visible, a new Function with delayed execution is returned after bind) testBindBar (); // 888

Note the understanding of this in prototype.

The above in-depth analysis of the JavaScript function currying colihua is all the content that I have shared with you. I hope you can give us a reference and support for me.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.