装饰器:在描述符.value中访问时,“ this”是未定义的

时间:2018-12-19 17:11:09

标签: javascript typescript decorator

我正在尝试装饰器,我编写了一个装饰器,该装饰器基本上返回了一个执行某些`console.log的新函数。

这是我的装饰器的外观:

<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>


<div id="app" class="container">
  <fieldset v-for="(filters, key,index) in availableFilters">
    <label v-for="(count, value) in filters">
        <input type="checkbox" :data-filterName="this[filters]" :value="value"  v-model="selected[key]" @change="onchange"> {{value}} ({{count}})
    </label>
  </fieldset>
  <pre>{{selected}}</pre>
</div>

这就是我的使用方式:

function test(target, name, descriptor) {
    const original = descriptor.value;
    console.log("bbau");
    if (typeof original === 'function') {
        descriptor.value = function (...args) {
            console.log(`Arguments: ${args}`);
            try {
                console.log("executing");
                const result = original.apply(this, args);
                console.log("done");
                console.log(`Result: ${result}`);
                return result;
            } catch (e) {
                console.log(`Error: ${e}`);
                throw e;
            }
        }
    }
    return descriptor;
}

`` 但是,执行时会引发错误:class TestController extends BaseController<//..> { // ... @test testIt(req: Request, res: Response) : Response { this.sendResponse(); } sendResponse(options: ISendResponseOptions, res: Response) : Response { // return response } }

有什么想法吗?谢谢!

1 个答案:

答案 0 :(得分:3)

当您要从声明函数的上下文中捕获this时(或this无关紧要时),通常应使用箭头函数。在这种情况下,您确实希望this是调用该函数的对象,因此您应该使用常规函数:

const test = (target, name, descriptor) => {
    const original = descriptor.value;
    if (typeof original === 'function') {
          descriptor.value = function (...args) {
            console.log(`Arguments: ${args}`);
            try {
                console.log("executing");
                const result = original.apply(this, args);
                console.log("done");
                console.log(`Result: ${result}`);
                return result;
            } catch (e) {
                console.log(`Error: ${e}`);
                throw e;
            }
        }
    }
    return descriptor;
}

您可以在playground

中对其进行测试

如果将此函数用作另一个函数的参数,则还应该调用bind来为该函数设置this(否则,调用者将确定this的值):< / p>

router.route("/").post(testController.testIt.bind(testController))