Bind variables to callback function

前端 未结 1 804
逝去的感伤
逝去的感伤 2020-11-27 04:24

I\'m calling some database functions from my request handlers. All of these functions do separate "error callbacks" for handling errors. Example:

fu         


        
相关标签:
1条回答
  • 2020-11-27 04:52

    Binding is simple!

    db.startDatabaseConnection(function(){
      // whatever
    }, onError.bind(this, var1, var2));
    

    You can learn more about binding by clicking this awesome link, even though the link is sort of long.

    Here's a real basic demo

    // a function
    var something = function (a, b, c) {
      console.log(a, b, c);
    };
    
    // a binding of something with 3 defined args
    var b = something.bind(null, 1, 2, 3);
    
    // call b
    b();
    //=> 1 2 3
    

    Behind the scenes, this is basically what's happening

    // ES6
    const myBind = (f, context, ...x) =>
      (...y) => f.call(context, ...x, ...y);
    
    // ES5
    var myBind = function(fn, context) {
      var x = Array.prototype.slice.call(arguments, 2);
      return function() {
        var y = Array.prototype.slice.call(arguments, 0); 
        return fn.apply(context, x.concat(y));
      };
    };
    
    var b = myBind(console.log, console, 1, 2, 3);
    
    b();
    // => 1 2 3
    
    b(4,5,6)
    // => 1 2 3 4 5 6 
    

    Context?

    Context allows you to dynamically change the this of your function. Note you can only bind the context of functions defined with the function keyword; arrow functions have a lexical this that cannot be manipulated. This is shown for sake of completeness, but I do advise against this kind of program. It's usually better to just use another function parameter instead of relying on dynamic function context, this. Supporting context switching like this is to enable object-oriented style in JavaScript. Unless you are using this style, I see no reason to pay attention to context.

    const getCanvas = (id) =>
      document.getElementById(id).getContext('2d')
    
    const draw = function (canvas, x = 0, y = 0)
    { canvas.beginPath()
      canvas.strokeStyle = this.color             // `this` refers to context!
      canvas.rect(x, y, this.width, this.height)  // `this` refers to context!
      canvas.stroke()
    }
    
    // create two contexts
    const contextA =
      { color: 'blue', width: 10, height: 10 }
      
    const contextB =
      { color: 'green', width: 10, height: 20 }
    
    // bind the draw function to each context and the canvas
    const drawA =
      draw.bind(contextA, getCanvas('main'))
      
    const drawB =
      draw.bind(contextB, getCanvas('main'))
    
    // call the bound drawing functions normally
    // draw three blue squares
    drawA(0, 0)
    drawA(20, 0)
    drawA(40, 0)
    
    // and one green rect
    drawB(80, 0)
    <canvas id="main"></canvas>

    Partial application

    Similar to binding is Partial Application

    In computer science, partial application (or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity.

    Here we could make a very simple partial helper procedure which helps us accomplish this

    const identity = x =>
      x
    
    const partial = (f = identity, ...x) =>
      (...y) => f (...x, ...y)
    
    const foo = (...all) =>
      console.log ('array of', all)
    
    partial (foo, 1, 2, 3) (4, 5, 6)
    // 'array of', [ 1, 2, 3, 4, 5, 6 ]


    Currying

    Currying is related to, but not the same as, binding or partial application

    In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument.

    const identity = x =>
      x
    
    const curry = (f = identity, arity = f.length) => x =>
    {
      const next = (xs = []) =>
        xs.length >= arity
          ? f (...xs)
          : x => next ([ ...xs, x ])
      return next ([ x ])
    }
    
    const foo = (a, b, c) =>
      console.log ('a', a, 'b', b, 'c', c)
    
    curry (foo) (1) (2) (3)
    // 'a' 1 'b' 2 'c' 3
    
    curry (foo) ('choo') ('bye') ()
    // 'a' 'choo' 'b' 'bye' 'c' undefined

    0 讨论(0)
提交回复
热议问题