23

我正在使用Function.prototype.bind. 在某些情况下更改函数范围(即值)
似乎非常有用。this

但是,一旦您这样做了,您似乎就无法更改范围:bind

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

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

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

4

3 回答 3

27

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),因此将真正执行函数中的上下文。

于 2012-05-09T20:09:11.420 回答
25

我认为用图片来说明Win32 的答案会很有用。

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

给定一个包装链,除了最里面的任何上下文都会丢失。
因此,一旦使用bind.

链式绑定调用

于 2012-05-09T21:26:54.807 回答
2

这实际上会解决你的问题

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 似乎都得到了相同的结果,有时普通版本更快,有时覆盖更快。

于 2019-02-08T09:31:59.467 回答