This is the fifth day of my participation in the August More text Challenge. For details, see: August More Text Challenge

1. To convert a function that takes multiple arguments to a function that takes a single argument (a single argument being the first of many arguments) and returns a new function that takes the remaining arguments and returns the result, i.e., f(a, b, c) to the callable f(a)(b)(c).

Function curlization idea: a JS preprocessing idea, reduce generality, improve applicability.

Features:

  • Parameters of reuse: You need to enter multiple arguments. Finally, you only need to enter one. The rest is obtained using arguments
  • Return early: Avoid repeatedly judging whether a condition is met. If it is not met, return will not continue to perform the following operations
  • Delay theAvoid repeating the process until you really need the results
// The normal add function
function add(x, y) {
    return x + y
}

/ / after Currying
function curryingAdd(x) {
    return function (y) {
        return x + y
    }
}

add(1.2)           / / 3
curryingAdd(1) (2)   / / 3
Copy the code

Advanced currying implementation

function curry (fn, currArgs) {
    return function() {
        let args = [].slice.call(arguments);
        // If the last parameter currArgs is not provided on the first call, no args concatenation is required
        if(currArgs ! = =undefined) {
            args = args.concat(currArgs);
        }
        // Call recursively
        if (args.length < fn.length) {
            return curry(fn, args);
        }
        // Exit recursively
        return fn.apply(null, args); }} orfunction currying(fn, ... args) {
  if (args.length >= fn.length) {
    returnfn(... args); }else {
    return (. args2) = >currying(fn, ... args, ... args2); }}function sum(a, b, c) {
  return a + b + c;
}

let curriedSum = curry(sum);

alert( curriedSum(1.2.3));// 6, can still be called normally
alert( curriedSum(1) (2.3));// 6, the first parameter of the curryization
alert( curriedSum(1) (2) (3));// 6, full currying
Copy the code

Currie use scenarios

1. Parameter reuse

Reduce the repeated passing of invariable parts of the parameter

function uri (protocol,hostname,pathname){
    return `${protocol}${hostname}${pathname}`;
}

const uri1 = uri("https://"."www.site.com"."/page1");
const uri2 = uri("https://"."www.site.com"."/page2");
console.log(uri1);
console.log(uri2);


// Convert to a Curryized function
function uri_curring (protocol){
    return function(hostname,pathname){
        return `${protocol}${hostname}${pathname}`; }}const uri_https = uri_curring("https://");
console.log(uri_https);
const uri1 = uri_https("www.csdn.net"."/page1");
const uri2 = uri_https("www.baidu.com"."/page2");
console.log(uri1); // "https://www.csdn.net/page1"
console.log(uri2); // "https://www.baidu.com/page2"
Copy the code

2. Confirm in advance

Event listening: Performance will suffer because of the unnecessary performance overhead of running the if() statement every time on earlier versions of Internet Explorer.
var on = function(element, event, handler) {
    if (document.addEventListener) {
        if (element && event && handler) {
            element.addEventListener(event, handler, false); }}else {
        if (element && event && handler) {
            element.attachEvent('on'+ event, handler); }}}// Run the whole function once
var on = (function() {
    if (document.addEventListener) {
        return function(element, event, handler) {
            if (element && event && handler) {
                element.addEventListener(event, handler, false); }}; }else {
        return function(element, event, handler) {
            if (element && event && handler) {
                element.attachEvent('on'+ event, handler); }}; }}) ();// The isSupport parameter is set to isSupport. // The isSupport parameter is set to isSupport
var on = function(isSupport, element, event, handler) {
    isSupport = isSupport || document.addEventListener;
    if (isSupport) {
        return element.addEventListener(event, handler, false);
    } else {
        return element.attachEvent('on'+ event, handler); }}Copy the code

3. Delay operation

Latency is also an important use case for Currying, as can bind and arrow functions.

function hello(name) {
    console.log('Hello, ' + name);
}
setTimeout(hello('dreamapple'), 3600); // Execute immediately, not after 3.6s


setTimeout(function() {
    hello('dreamapple');
}, 3600); // After 3.6 seconds
setTimeout(() = > {
    hello('dreamapple');
}, 3600);  // After 3.6 seconds

// Bind delays execution: the bind method is required to force binding to the context, i.e. the first argument to bind is referred to as this when the original function is run
setTimeout(hello.bind(this.'dreamapple'), 3600); // Execute the function after 3.6s

// Curlize delay execution
function curryingHelper(fn) {
    var _args = Array.prototype.slice.call(arguments.1);
    return function() {
        var _newArgs = Array.prototype.slice.call(arguments);
        var _totalArgs = _args.concat(_newArgs);
        return fn.apply(this, _totalArgs); }}setTimeout(curryingHelper(hello, 'dreamapple'), 3600); // Execute the function after 3.6s
Copy the code

Classic topic

To determine the parametersFunction currying implementation of

function sum(a,b,c,d){
    return a+b+c+d
}
function curry(fn){
    return function sum(. args){
        if(args.length<fn.length){ // Determine whether the accepted argument is smaller than the length of the function's argument
           return function(){  // The parameter is not long enough. Accept the passed parameter again
                returnsum(... args,... arguments) } }returnfn(... args)// Do not require change this,}}let curried = curry(sum)
console.log(curried(1) (2) (3) (4))/ / 10
console.log(curried(1.2) (2.4)) / / 9
Copy the code

Uncertain parameterssum(1)(2)(3)(4)(5)… (n)


function curry(fn){
    let parmas = []
    return function sum(. args){
        if(args.length){// Check whether there are parameters
            parmas = [...parmas,...args]
            return sum
        }
        return fn(parmas)
    }
}
function add(arr){
   return arr.reduce((acc,item) = >{
        return acc+item
    })
}
 
let curried = curry(add)
console.log(curried(1) (2) (3) (4) (10.20) ())/ / 40
// Note how the last call is used. The () call does not pass any arguments, so it will jump the judgment and call the cumulative function
Copy the code
// Define a toString method inside the method that returns the computed value
function curry(. args){
	let parmas = args
    function sum(){
        parmas = [...parmas,...arguments]
        return  sum
    }
    sum.toString=function(){
       return parmas.reduce((acc,item) = >{
       	 return acc+item
       })
       
    }
    return sum
}
console.log(curry(1) (2) (3) (10) (10.20).toString()) / / 40
Copy the code