Могу ли я получить несвязанную функцию из связанной функции в JavaScript? - программирование
Подтвердить что ты не робот

Могу ли я получить несвязанную функцию из связанной функции в JavaScript?

Я получаю свою голову, завернутую в карри и другие методы, используя 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

Можно ли вообще восстановить исходную несвязанную функцию из связанной функции?

4b9b3361

Ответ 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);
}

Но поскольку внутренняя функция, возвращаемая связыванием, действует как замыкание, где исходный контекст является первым, связанным первым (self), который будет контекстом с вашей функцией, будет действительно выполнен.

Ответ 2

Я подумал, что было бы полезно проиллюстрировать ответ Win32 с изображением.

Обертка, сгенерированная с помощью bind, гарантирует, что ваша функция вызывается с заданным контекстом независимо от того, что. Такая оболочка всегда игнорирует свой собственный контекст.

Учитывая цепочку оберток, любой контекст, но самый сокровенный, теряется.
Поэтому нет способа изменить контекст после его установки с помощью bind.

Chained bind calls

Ответ 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, кажется, получают один и тот же результат, иногда нормальная версия быстрее, а переопределенная - быстрее.