【问题标题】:Can I get an unbound function from a bound function in JavaScript?我可以从 JavaScript 中的绑定函数获取未绑定函数吗?
【发布时间】:2012-05-09 19:47:27
【问题描述】:

我对使用 Function.prototype.bind 的柯里化和其他技术一头雾水。
在某些情况下更改函数范围(即this 值)似乎非常有用。

但是it looks like you can't change the scope with bind 一旦你已经这样做了:

function f = obj.method.bind(42); 
function g = obj.method.bind('Hi');

function f2 = f.bind('Hi'); // “this” is still 42

是否可以从绑定函数中检索原始未绑定函数?

【问题讨论】:

  • @Martin:我现在正在制作小提琴。对于知道答案的人来说,这似乎是一个非常简单的问题,因此我在没有事先研究的情况下发布了一个问题。
  • @Martin:我只是checked my assumptions,看起来我不能用bind 两次更改范围。那么,有可能吗?有没有某种unbind
  • 是的,我和菲利克斯一起做这个 - 不可能,何塞
  • 我不知道这怎么可能,但话又说回来,我想不出一个需要它的情况。

标签: javascript function bind ecmascript-5


【解决方案1】:

bind 方法的基本作用类似于(不完全是,因为参数被切片以排除上下文):

function bind(context) {
    var self = this;
    return function() {
        self.apply(context, arguments);
    }
}

所以基本上它会返回另一个函数,该函数将使用给定的上下文和参数调用自身。如果你再次bind 它,你将绑定这个新创建的函数,就像bind 的实现方式如下:

 function bind(context) {
    var self = this;
    return function() {
        self.apply(context, arguments);
    }.bind(otherContext);
}

但是由于 bind 返回的内部函数充当了一个闭包,其中原始上下文是第一个绑定的 (self),因此将真正执行函数中的上下文。

【讨论】:

    【解决方案2】:

    我认为用图片说明Win32's answer 会很有用。

    bind 生成的包装器确保您的函数在给定的上下文中调用无论如何
    这样的包装器将总是忽略它自己的上下文

    给定一个包装链,除了最里面的任何上下文都会丢失。
    因此,一旦使用bind 设置上下文,就无法更改上下文。

    【讨论】:

      【解决方案3】:

      这实际上可以解决您的问题

      const bind = Function.prototype.bind;
      Object.defineProperty(Function.prototype, 'bind', {
          value: function () {
              const result = bind.apply(this, arguments);
              result.source = (this.source || this);
              return result;
          }
      });
      

      现在您可以通过source 属性来获取原始函数。 这可能会导致其他问题,但性能似乎不是其中之一,https://jsperf.com/bind-override/1

      IE、Edge、Firefox 和 Chrome 似乎都得到了相同的结果,有时普通版本更快,有时覆盖更快。

      【讨论】:

      • 很高兴知道为什么这被否决了,所以我可以改进答案!
      • 我的猜测是你被否决了,因为这改变了 Function 原型的默认行为,这通常是不受欢迎的。我喜欢你的解决方案,我将在我的代码中使用它。 :)
      • 另外,我建议将result.source = this 更改为result.source = (this.source || this),这样无论函数绑定多少次,源都将保持不变。
      • @Mr.X 好主意,我已经按照您的建议进行了更改。
      猜你喜欢
      • 2012-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-17
      • 2016-04-17
      • 2021-12-13
      • 2013-03-13
      相关资源
      最近更新 更多