zoukankan      html  css  js  c++  java
  • Bind, Call and Apply in JavaScript

    原文地址1:https://variadic.me/posts/2013-10-22-bind-call-and-apply-in-javascript.html

    原文地址2:http://blog.csdn.net/rznice/article/details/26134201

    翻译:

    Bind, Call and Apply in JavaScript 有一天,我在tweet中看到了这个整洁的JS代码片段。

    var bind = Function.prototype.call.bind(Function.prototype.bind); // #fp

    乍一看,我可以猜到它做了什么。 它将x.y(z)变成y(x,z)。 有了孩子般的欢乐,我把它给我的同事。 他们问我做什么。 我打开我的嘴来解释和...没有出来。 我转身走开。

    你看,最好的代码将立即告诉你它做什么。 有了一些功能JavaScript的经验,并且阅读了功能JavaScript和JavaScriptAllongé(这两本神奇的书),我读到它没有问题。 但解释它(和为什么一个人甚至会关心这样做)给没有经验的功能编程的人?

    我决定以我的方式通过它,用简单的例子和许多评论。 这是结果。

    // Set up a simple object to use as "context"
    //设立一个简单地对象作为“上下文”
    var context = { foo: "bar" };
    
    // A function that uses a reference to a variable called "foo"
    // on the "this" context.
    //一个在this上下文中指向foo变量的函数
    function returnFoo () {
      return this.foo;
    }
    
    // This variable does not exist on scope, so is undefined.
    // 变量在作用域中不存在,因此显示undefined
    returnFoo(); // => undefined
    
    // But if we bind the function to the context.
    // 如果我们把它绑定在context上下文中
    var bound = returnFoo.bind(context);
    
    // The name variable is now in scope.
    // 现在的作用域中有这个变量了
    bound(); // => "bar"
    
    //
    // That's what Function.prototype.bind does. Since returnFoo
    // is a function, it inherits the function prototype.
    // 这就是Function.prototype.bind的作用.   
    //由于returnFoo也是函数,因此它继承了function的原型
    //
    // If you enjoyed that, keep reading. It just gets better.
    // 如果你觉得享受,接着往下读,下面更精彩
    //
    
    
    // There are many ways of attaching a context to a function.
    // 有许多方法将函数绑定在一个上下文中
    // Call and apply let you call a function with a given context.
    // Call和Apply让你能在上下文中调用函数
    returnFoo.call(context); // => bar
    returnFoo.apply(context); // => bar
    
    // Including adding the function to the object.
    // 将函数添加到对象中
    context.returnFoo = returnFoo;
    context.returnFoo(); // => bar
    
    //
    // Now let's get freaky with it.
    // 现在我们来玩一点诡异的东西
    //
     
     
    // Array.prototype has this sweet method called slice.
    // You call it on an array, and it gives you a copy of
    // the array from start index to end index (exclusive).
    // Array.prototype 中有一个叫做slice的方法
    // 对一个数组调用slice,可以返回一个从start index到end index的数组
    [1,2,3].slice(0,1); // => [1]
    
    // So we grab slice and assign it to a local variable.
    // 因此我们把Array.slice赋值给一个本地变量slice
    var slice = Array.prototype.slice;
    
    // slice is now "unbound". As Array.prototype.slice usually
    // acts on the context it is given, or "this", it will
    // no longer work.
    //现在的slice是"自由的",由于Array.prototype中的slice一般指定了上下文
    //或者默认为this,此时slice将不起作用
    slice(0, 1); // => TypeError: can't convert undefined to object
    slice([1,2,3], 0, 1); // => TypeError: ...
    
    // But if we recall apply and call, they let us supply a context.
    // 但是如果我们使用call或者apply,slice又将在一个上下文中执行
    slice.call([1,2,3], 0, 1); // => [1]
    
    // Apply works like call, but takes arguments as an array.
    // Apply和Call差不多,知识参数要放在一个数组中
    slice.apply([1,2,3], [0,1]); // => [1]
    
    // It sure gets old using .call though. What if we bind it?
    // That's right! Let's bind "call" to slice. Yes.
    // 使用call没错了,那么能不能使用bind呢?
    // 没错,我们来把"call"绑定在slice上
    slice = Function.prototype.call.bind(Array.prototype.slice);
    
    // Now slice uses the first argument as context.
    // 现在slice可以把第一个参数作为上下文了
    slice([1,2,3], 0, 1); // => [1]
    
    //
    // Pretty cool huh? But I got one last thing for you.
    // 很酷,对吧。现在再来完成一件事
    //
    
    // Let's put "bind" itself through the same process
    // we did "slice".
    // 现在我们对bind本身做一件刚才对silce做的事
    var bind = Function.prototype.call.bind(Function.prototype.bind);
    
    // Wrap your mind around that. Think about it.
    // What does it do? We are flipping "call",
    // returning a function that takes a function
    // and a context and returning a fully bound function.
    // 在这里总结一下,好好想想
    // 发生了什么事? 我们改变了call,
    // 返回一个接受函数的函数和上下文并返回完全绑定的函数。
    
    
    // Bringing back our original example.
    // 回到最初的例子
    var context = { foo: "bar" };
    function returnFoo () {
      return this.foo;
    }
    
    // And using our new amazing "bind".
    // 现在来使用神奇的"bind"函数
    var amazing = bind(returnFoo, context);
    amazing(); // => bar

     

    分析:

    var slice = Array.prototype.slice;
    slice.bind([1,2,3], 0, 1)();// => [1]

    所以,这样直接绑定也是有效的。

  • 相关阅读:
    NOIP201208同余方程
    NOIP模拟赛 最佳组合
    NOIP模拟赛 拓展
    CF1253E Antenna Coverage(DP)
    LOJ6033「雅礼集训 2017 Day2」棋盘游戏 (博弈论,二分图,匈牙利算法)
    CF582E Boolean Function(DP,状态压缩,FMT)
    CF750G New Year and Binary Tree Paths(DP)
    Codeforces Round 596 题解
    AGC008E Next or Nextnext(组合计数,神奇思路)
    ARC082E ConvexScore(神奇思路)
  • 原文地址:https://www.cnblogs.com/xmyun/p/6434056.html
Copyright © 2011-2022 走看看