【问题标题】:What's the point of JavaScript decorators?JavaScript 装饰器的意义何在?
【发布时间】:2019-01-20 05:37:16
【问题描述】:

我在 Google 上搜索了 JavaScript 装饰器,但我不确定使用装饰器调用函数和正常调用函数之间的区别是什么。

function myFunction(text) {
  console.log(text)
}

myFunction() vs @myFunction vs @myFunction()

我觉得我在这里大错特错。谁能解释一下?

【问题讨论】:

  • 装饰器附在某物上,你不能自己调用​​它们
  • @UnholySheep 不确定您所说的“附加”是什么意思。你能详细说明一下吗?
  • @shash678 谢谢,我去看看。
  • 装饰器最终只是函数,正如@UnholySheep 所提到的。他们的目的是改变常规行为。 IE Angular 使用它们来指导编译器如何编译某个类,无论它应该是服务、组件还是指令

标签: javascript function functional-programming decorator


【解决方案1】:

有了装饰器,我们可以不用扩展。 mutli继承为类添加了一些方法。

function withLoginStatus( DecoratorClass ) {
    return class extends DecoratorClass {
        constructor(...args ) {
            super(...args);
            this.isLoggedIn = false;
        }

        setLoggedIn() {
            console.log('setLogin!');
            this.isLoggedIn = true;
        }
    }
}


@withLoginStatus
class User {
    constructor(firstname, lastName) {
        this.firstname = firstname;
        this.lastName = lastName;
    }
    getFullName() {
        return `${this.firstname} ${this.lastName}`;
    }
}

【讨论】:

    【解决方案2】:

    装饰器用于启用关注点分离。考虑以下函数:

    function add(a, b) {
      return a + b;
    }
    

    这一切都很好,花花公子。但是假设您要添加日志记录:

    function add(a, b) {
      const sum = a + b;
      console.log(a, b, sum);
    }
    

    现在函数变得更长更复杂,并且将两个实际上没有任何关系的东西(求和和记录)混为一谈。更好的方法是:

    function logs(f) {
      return function(...args) {
        const result = f(...args);
        console.log(args, result);
        return result;
      };
    };
    
    const addAndLog = logs(add);
    

    这就是装饰器。您所说的(即 JavaScript 装饰器提案)只是上述模式的语法快捷方式。这里logs 是一个装饰器,它为传入的函数添加了一项功能,即无需使用大量无关代码使函数复杂化即可进行日志记录的能力。该提案目前仅限于类和方法,但我发现用普通函数在概念上更容易解释。

    【讨论】:

      【解决方案3】:

      装饰器用于从字面上装饰一个函数。

      假设你想输入你自己的装饰器,它可以用来查看一个函数需要运行多长时间。你可以写一个装饰器@time() 来做这件事。完成后,您可以在要跟踪的每个函数之前使用此装饰器。

      装饰器用作高阶函数,主要是为了让您的代码具有功能组合!

      一个很好的例子是 Angular 中的 @Component() 装饰器。虽然在你的类之前使用这个装饰器,Angular 知道它必须将它作为一个组件来处理,并在幕后用它做几个方法。

      【讨论】:

      • 所以它用于将核心方面修改为常规类,这是我从中得到的(?)
      • @apxx 在某种程度上,是的。您可以通过说它用于“拉皮条”您的类、方法、变量来解释它......如果我要在 Angular 中声明一个输入变量,我会使用类似:@Input() public tmp: string,这样 Angular 就知道它不是只是一个常规变量,但它可以在输入标签中使用!
      猜你喜欢
      • 2011-09-14
      • 2021-12-20
      • 2010-12-23
      • 2018-07-20
      • 2013-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      相关资源
      最近更新 更多