Refer to the link

The function is currified

meaning

Corey: is the fixed part parameters, function returns a accept the rest of the parameters, also known as part of the calculation function, the purpose is to narrow scope of application, create a targeted stronger function, core idea is to put the multi-parameter incoming function parameters (in part) into the single function, internal back again the next single parameter function (in part), dealing with residual function in turn

Anti-currification: Extend the scope of application by creating a broader function so that a method that is only suitable for a particular object can be extended to more objects

General implementation

  // The first implementation
  Function.prototype.unCurrying = function() {
    const self = this
    / /... The REST method is equivalent to destructuring assignment using ES6 syntax using REST to take an array of incoming arguments, equivalent to arguments REST where the value is an array of all the arguments passed in
    return function(. rest) {
      return Function.prototype.call.apply(self, rest)
    }
  }
  const push = Array.prototype.push.unCurrying()
  /* * 1 adds an unCurrying method to a Function prototype, and saves a method that uses unCurrying while performing it into self * * 2 Use apply to give call the Function that you want to borrow as this, and pass in the subsequent parameter */

  // The second implementation
  Function.prototype.unCurrying = function() {
    return this.call.bind(this)}// The third implementation
  function unCurrying(fn) {
    return function(tar, ... argu) {
      return fn.apply(tar, argu)
    }
  }
Copy the code

Use anti-Cremation

  Function.prototype.unCurrying = function() {
    const self = this
    return function(. rest) {
      console.log(rest, 'uncurrying rest')
      
      return Function.prototype.call.apply(self, rest)
    }
  }
  const push = Array.prototype.push.unCurrying()
  ~function(. rest) {
    console.log(rest, 'before')
    push(rest, 4.5)
    console.log(rest, 'after')
  }(1.2.3)
Copy the code

In fact, anti – Corrification reflects a kind of idea-expanding method’s application scope

  Function.prototype.unCurrying = function() {
    const self = this
    return function(. rest) {
      console.log(rest, 'uncurrying rest')
      
      return Function.prototype.call.apply(self, rest)
      // Array.prototype.push.call({a: 3}, 4, 5)}}const push = Array.prototype.push.unCurrying()
  ~function() {
    let rest = {a: 3}
    console.log(rest, 'before')
    push(rest, 4.5)
    console.log(rest, 'after')
  }(1.2.3)
Copy the code

You can use unCurrying methods as long as they are methods

  // call
  var call = Function.prototype.call.unCurrying()
  function $(id) {
    return this.getElementById(id)
  }
  // call()
  call($, document.'demon')
  / problem solving steps are * * * = > Function. The prototype. Call. Apply (Function. The prototype. Call, [$, document, 'demon']) * => Function.prototype.call.call($, document, 'demon') * => $.call(document, 'demon') * => document.getElementById('demon) */
  // unCurrying borroys itself
  const unCurrying = Function.prototype.unCurrying.unCurrying()
  const map = unCurrying(Array.prototype.map)
  map({0: 4.1: 'a'.2: null.length: 3}, n= > n + n)
  / * * const map = unCurrying (Array) prototype) map) step * = > Function. The prototype. Call. Apply (Function. The prototype. UnCurrying, [Array.prototype.map]) * => Function.prototype.unCurrying.call(Array.prototype.map) * => Array.prototype.map.unCurrying() * => map = Array.prototype.map.unCurrying() * => map({0: 4, 1: 'a', 2: null, length: 3}, n => n + n) * => Function.prototype.call.apply(Array.prototype.map, [{0: 4, 1: 'a', 2: null, length: 3}, n => n + n]) * => Array.prototype.map.call({0: 4, 1: 'a', 2: null, length: 3}, n => n + n) * => {0: 4, 1: 'a', 2: null, length: 3}.map(n => n + n) * => {0: 8, 1: 'aa', 2: 0, length: 3} */
Copy the code

conclusion

The function is currified

  function(arg1, arg2) / /function(arg1) (arg2)
  function(arg1, arg2, arg3) / /function(arg1) (arg2) (arg3)
  function(arg1, arg2, arg3, arg4) / /function(arg1) (arg2) (arg3) (arg4) Copy the code

The curry

  obj.fn(arg1, arg2)             // fn(obj, arg1, arg2)
Copy the code

Key knowledge analysis

  1. Function.prototype.call.apply(self, rest)

    Example:

      Math.Max.apply([], [1.2.3])
    Copy the code

    Apply and replace math with [], then Max and pass [1,2,3]. [1,2,3] flattens to 1,2,3 because of apply

    Function. The prototype. Call. Apply (self, rest) process

    • Function.prototype.call.apply(Array.prototype.push, rest)
    • Array.prototype.push.call(... rest) So when passing rest, the object you need to operate on comes first, so call can bind this
    • rest[0].push(rest.shift(1))
      var obj = {a: 3}
      Array.prototype.push.call(obj, 4.5) / / 2
      obj // {0: 4, 1: 5, a: 3, length: 2}
      var obj = {a: 3.b: 3}
      Array.prototype.push.call(obj, 4.5) / / 2
      obj //{0: 4, 1: 5, a: 3, b: 3, length: 2}
    Copy the code