Deep analysis of functions in JavaScript currying Corrie _javascript techniques

Source: Internet
Author: User
Tags javascript currying

The source of curry and the name of the mathematician Haskell Curry (the programming language Haskell is also named under his name).

Gerty is often called partial evaluation, the meaning of the function is to pass the parameters, each pass the argument after the application of parameters, and return a more specific function to accept the remaining parameters, which can be nested multi-layer such as the acceptance of the partial parameter function, until the final result returned.

Therefore, the process of gerty is to gradually transfer the parameters, gradually narrowing the scope of application of the function, and gradually solve the process.

To curry a sum function
According to the 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] 

As you can see, concat3wordscurrying ("foo") is a function, each call returns a new function that accepts another call, and then returns a new function until the result is returned, the distribution is solved, and the layer is progressive. (PS: This utilizes the features of closures)

So now we go further, if you require more than 3 parameters to be passed, you can pass any number of parameters, when the parameters are not passed output?

Let's start with a common implementation:

var add = function (items) {return 
  items.reduce (function (a,b) {return 
    a+b 
  }); 
 

But if you need 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 
  }); 
 

Fortunately, with the map and reduce functions, if you follow this pattern and now you want to add 1 to each item, then we need to replace the function in the map.

Here's a look at the Gerty implementation:

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);  The calling form is flexible, one call can be entered with a single parameter or more, and a chained call of sum is supported 
; 
Console.log (sum ());  1000 (plus total calculation) 

The above adder is a gerty function that returns a new function that receives a new parameter that can be divided into batches and deferred to the last calculation.

General functions of the Gerty

More typically, Gerty will encapsulate the last calculation into a function, then pass the function as a parameter into the Gerty function, which is clear and flexible.

For example, with each item multiplied by 10, we can pass the handler 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) (+); 
Sum (); 
Console.log (sum ());   1000 (only true when blank calls are counted)

So sum = currying (multi), the call is very clear, the use of the effect is also called gorgeous, such as to add multiple values, you can take multiple values as a parameter sum (1,2,3), can also support chained calls, SUM (1) (2) (3)

The basis of the curry

The above code is actually a higher order function (High-order function), which is a function of the operation function that receives one or more functions as arguments and returns a new function. In addition, it relies on the characteristics of the closure to hold the parameters entered in the middle process. That

Functions can be passed as arguments
function can be used as the return value of a function
Closed Bag
The role of the curry
Deferred calculation. The example above is already very low.

Parameter reuse. When the same function is called more than once, and the majority of the arguments passed are the same, the function may be a good candidate for Gerty.

Create a function dynamically. This can be done after the partial calculation of the results, on this basis dynamically generated new functions to deal with the subsequent business, so that the redundant calculation is omitted. Alternatively, you can dynamically create a new function by using a subset of the parameters that will be passed in to the calling function, and the new function saves the repeated incoming arguments (not every time in the future). For example, the event browser adds an auxiliary method for an event:

 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 every time you add event handling if...else ..., in fact, in a browser as long as a decision on it, the results based on a decision after the dynamic generation of new functions, you do not have to recalculate.

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);} 
      );};} 
   

This example, the first time if...else ... After judgment, a partial calculation is completed, and a new function is dynamically created to handle the parameters passed in later, which is a typical gerty.

Function.prototype.bind method is also the application of Gerty

Unlike the Call/apply method, the Bind method sets the first argument to the context in which the function executes, and the other arguments are passed to the calling method (the body of the function itself is not executed, can be seen as deferred execution), and dynamic creation returns a new function, which is consistent with the characteristics of Cory.

var foo = {x:888}; 
var bar = function () { 
  console.log (this.x); 
Bind (foo);        Bind 
Bar ();           888 

The following is a simulation of a bind function that Testbind creates and returns a new function that binds the function that really wants to perform a business to the context in which the actual argument is passed, deferred execution.

Function.prototype.testBind = function (scope) { 
  var fn = this;          This refers to a function that invokes the Testbind method, return 
  function () {return 
    fn.apply (scope); 
  } 
; 
var testbindbar = Bar.testbind (foo); Binding foo, delaying execution of 
Console.log (Testbindbar);       function (visible, a new function that is returned after bind is a deferred execution) 
Testbindbar ();            888 

Here you should pay attention to the understanding of this in prototype.

The above in-depth analysis of JavaScript functions currying Gerty is a small series to share all the content, hope to give you a reference, but also hope that we support the cloud-dwelling community.

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.