Декорирование функций в JavaScript - PullRequest
0 голосов
/ 02 июня 2018

Вот простой шаблон декоратора, который модифицирует нормальную функцию:

function decorator1(f){
   function wrapper(...args){
       pre();
       return f(...args);
       post();
   }
   return wrapper
}

Теперь предположим, что есть объект obj, и у него есть свойство prop в его прототипе.По какой-то причине я хочу изменить связанную функцию объекта.

Я не могу использовать этот шаблон напрямую для украшения связанной функции obj.prop, потому что, если я передам ее в качестве аргумента decorator, он выиграетне вызывается с правильным объектом в wrapper, потому что JavaScript использует , вызывающий для передачи правильного объекта.Так что obj.prop() является контекстно-зависимым, а obj.prop - нет.Есть ли способ преодолеть это ограничение?

Если это невозможно, мне нужно либо:

Изменить шаблон, чтобы он принимал объект и свойство как 2 разных аргумента и заставлял его работать.

function decorator2(o, f){
   function wrapper(...args){
       pre();
       return o.f(...args);
       post();
   }
   return wrapper
}

obj.prop = decorator2(obj, prop);

Передайте связанную функцию, которая по какой-то причине, по моему мнению, является жестко запрограммированной.

// This creates a bound function to itself.
obj.prop = obj.prop.bind(obj)
// This modifies it.
obj.prop = decorator1(obj.prop)

Какая из них предпочтительнее?Я бы выбрал первое, потому что я думаю, что создание связанных функций не годится, если они вам действительно не нужны.

1 Ответ

0 голосов
/ 02 июня 2018

Вы можете просто использовать this в wrapper:

function decorate(f) {
    return function wrapper(...args) {
        pre();
        const res = f.apply(this, args); // or f.call(this, ...args)
//                          ^^^^
        post();
        return res; // make post() work
    };
}

При этом будет работать обычный obj.prop = decorate(obj.prop);.

...