【问题标题】:Decorating functions in JavaScriptJavaScript 中的装饰函数
【发布时间】:2018-11-12 07:39:05
【问题描述】:

这是一个简单的装饰器模式,它修改了一个普通的函数:

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)

哪一个更受欢迎?我会选择前者,因为我认为创建绑定函数并不好,除非你真的需要它们。

【问题讨论】:

    标签: javascript decorator


    【解决方案1】:

    您可以在wrapper 中使用this

    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); 就可以了。

    【讨论】:

    • 是的@Bergi,这是我尝试过的另一个。感谢您指出。这使得调用者有责任传递保留原始行为的对象,这是最干净的事情。我收到一个 JS Lint 警告说if a strict mode function is executed using function invocation 'this' will be undefined。我需要担心吗?我认为这实际上是最好的方法。
    • 错误代码为w040。根据stackoverflow.com/questions/7688765/…的答案,我可能可以忽略一些事情?
    • 是的,您应该忽略该警告。我们希望 this 在调用者没有提供时成为undefined,因为那样我们也不想向f 提供一个。
    猜你喜欢
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 2014-07-21
    • 2022-06-19
    相关资源
    最近更新 更多