What is currying

In computer science, Currying is the technique of taking A function A that takes n arguments, and transforming it into A function B that takes only one argument (the only argument in B is the first of A’s arguments).

And then what the new function B returns, again, is A function called C(notice what the old function A doesn’t have to return). This C function can take only one argument (the second argument of A)…… So you keep going back and forth until you return A function F that takes the NTH argument of A, and you say that’s the last function in F, and you execute it, and you return the final value.

Here’s an example:

// We want to implement a function that adds the parameters and returns the sumfunction adder(a, b) {
	returna + b; } adder (4, 6); // The result is: 10Copy the code

You could also write it like this.

function adder() {
	var sum = 0;
	for(var i=0; i<arguments.length; i++) sum += arguments[i];returnsum; } adder (4, 6); / / 10Copy the code

I’ll do it with currying

var adder = function(num) { var n = num; // The corresponding parameter is 4return function(y) {
        returnn + y; // return 4+6}} adder(4)(6) // 10Copy the code

Adder (4, 6) adder(4, 6) adder(4, 6) adder(4, 6) adder(4, 6) adder(4, 6) adder(4, 6)

As you can see, the adder function has an inner function that references n all the time, and this forms a closure. So Curryization is one of the applications of closures

The advanced

So you can sort of get a sense of what a currie is,

The original function adder (3,5,6,7,8,9) = = > adder (3) (5) (6) (7) (8) (9) ()

Note: the last call has no argument (), so adder can determine whether I want to continue adding or return the sum by deciding whether there are arguments

Or this is fine

Adder (5,6,7) adder(8,9) adder(Copy the code

So what are the benefits?

  • Delay the calculation. When you want the result, just adder()
  • It is usually a process of partial evaluation, passing parameters to the function step by step, gradually reducing the scope of application of the function, and gradually solving.

So when we write a function, we can write it with the idea of currying; But we can also take any existing function, and turn it into a Curryized idea and form, see the idea ~

Ex. :

It’s an old function

// Don't know thistest< span style = "box-size: inherit! Important; word-break: inherit! Important;"function test(name, id, num, score, height) {
    
}
Copy the code

To curify him is to curify him

Test (” Chen “, 45, 789, 284.2, 178) = = > test2 (” Chen “) (45) (789) (284.2) (178) ()

Among them, Test2 is the test after currie packaging

The idea of packaging is

  1. [” Chen “, 45, 789, 284.2, 178] [” Chen “, 45, 789, 284.2, 178]
  2. Test.apply (arr) is executed when there are no arguments
  3. So, what you’re doing is you’re saving a bunch of parameters first, and then you’re executing test one last time

The generic encapsulation code is as follows, be sure to understand!

The practical application

If that doesn’t help, let’s look at two practical examples

1. Browser events

Remember to distinguish between IE and non-IE events

var addEvent = function(el, type, fn, capture) {
    if(window.addEventListener) {
        el.addEventListener(type.function(e) {
            fn.call(el, e)
        }, capture)
    } else {
        el.attachEvent('on'+type.function(e) {
            fn.call(el, e)
        })
    }
}
Copy the code

That is, we will call addEvent, but each time we have to execute an internal if… else….

So we could have curialized, we could have changed it to

var curEvent = (function() {
    if(window.addEventListener) {
        return function(el, sType, fn, capture) { // return funtion
            el.addEventListener(sType, function() {
                fn.call(el, e)
            }, capture)
        }
    } else {
        return function(el, sType, fn) {
            el.attachEvent('on'+sType, function(e) { fn.call(el, e) }) } } }) var addEvent = curEvent(); // addEvent will get if.. else... The one in therereturnfunctionSo all you need to do is perform curEvent() once to determine if.. Otherwise, you don't need to judge addEventCopy the code

2. Bind to the function

We’ll always see a function that looks like test.bind(this), where bind is the idea of currying

Funtion.prototype.bind()

var foo = {
    x: 888
}
var bar = function(e) {
    console.log(this.x, e)
}
Function.prototype.testBind = function(scope) { var fn = this; // Point to barreturn function() {
        return fn.apply(scope, [].slice.call(arguments))
    }
}

var test= bar.testbind (foo) // bind foo to delay the execution of console.log(test)
test(2323) // Execute, the result is 888 2323Copy the code

Will be the first parameter to the incoming (foo), as a function of the execution context, and, the other parameters to the method called again (the function itself does not perform, made only bind binding, after function performs, equivalent to the deferred execution), so the equivalent of, bind the object and returns the function in advance, and then perform functions, Conforms to currie.

3. ApplyMiddle middleware in Redux

let store = applyMiddleware(middleware1,middleware2)(createStore)(rootReducer);

export default function createLogger({ getState }) {
      return (next) =>  // return function
        (action) => {
              const console = window.console;
              const prevState = getState();
              const returnValue = next(action);
              const nextState = getState();
              const actionType = String(action.type);
              const message = `action ${actionType}`;

              console.log(`%c prev state`, `color: #9E9E9E`, prevState);
              console.log(`%c action`, `color: #03A9F4`, action);
              console.log(`%c next state`, `color: #4CAF50`, nextState);
              return returnValue;
    };
}
Copy the code

Role summary

  • A js preprocessing idea; Use function execution can form a non-destructible scope principle, the content that needs to be pre-processed are stored in this non-destructible scope, and return a small function, we will execute this small function, the small function in the previous stored value for related operation processing. For example, if a function is run on both the mobile and PC terminals, the first 5 lines of code on both terminals are overlapping, and the following code is different, then the first 5 lines of code can be made into currie form, not to say the code, but the overlapping part of the function can be front-loaded
  • It is usually a process of partial evaluation, passing parameters to the function step by step, gradually reducing the scope of application of the function, and gradually solving.
  • pretreatment
  • Delay calculation
  • You can pass in the parameters you want, wait until you want the result, and then calculate it together
  • Parameters of reuse
  • Some parameters are the same, only need to pass once, do not need to pass every time, too tedious. For example the bind
  • Create functions dynamically. This can be a part of the calculation results, on the basis of dynamic generation of new functions to deal with the following business, so as to omit the double calculation. Or you can dynamically create a new function that holds the arguments that are passed repeatedly (not every time in the future) by partially applying the subset of the arguments that will be passed to the calling function. For example, the browser adds a helper method to the event.

Finally: if there is any mistake, please forgive me, and I will correct it immediately

Reproduced please indicate the source, thank you ~~

Next: DOM parsing and rendering with JS and CSS