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