ES6 JavaScript中的“@”符号有什么作用?(ECMAScript 2015)

75

我正在查看一些ES6代码,不明白在变量前加@符号的作用是什么。我找到的最接近的东西似乎与私有字段有关?

我查看了redux库中的代码:

import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'redux/react';
import Counter from '../components/Counter';
import * as CounterActions from '../actions/CounterActions';

@connect(state => ({
  counter: state.counter
}))
export default class CounterApp extends Component {
  render() {
    const { counter, dispatch } = this.props;
    return (
      <Counter counter={counter}
               {...bindActionCreators(CounterActions, dispatch)} />
    );
  }
}

这里是我在该主题上发现的博客文章:https://github.com/zenparsing/es-private-fields

在这篇博客文章中,所有的例子都是在类的环境下展示的-当符号在模块中使用时,它意味着什么?


1
这些被称为注解。 - Daniel A. White
9
这些不是ES6,而是一些实验性的转译工具。你提供的文章是一个ES7提案 - Bergi
2
你能在标题中添加一个 @,这样它就会出现在搜索 @ javascript 的结果中吗? - achalk
1
@adc17 已经完成了。好主意。 - baao
3个回答

90

我发现被接受的答案对于帮助我解决问题并不足够,因此我添加了更多细节来帮助其他人。

问题在于何为装饰器并不清晰。在给出的示例中,装饰器不仅仅是@符号,而是@connect函数。简而言之,@connect函数正在装饰CounterApp类。

那么在这种情况下它是在做什么呢?它正在将state.counter的值与类的props连接起来。请记住,在redux中,connect函数需要两个参数:mapStateToPropsmapDispatchToProps。在这个例子中,它只取了一个参数-mapStateToProps

我没有深入研究这个问题,但这似乎是一种封装您的状态到props和分派到props映射的方式,以便它们随附于您的组件而不是位于不同的文件中。


1
@connect确实可以做到这一点,但是一般而言,我会说使用装饰器我们可以轻松添加函数我看到@injectIntl()(用于react-intl)、@reduxForm(用于redux-form)和许多其他类似的用法。 - Do-do-new

42

这是一个修饰器。它是建议添加到ECMAScript中的内容。在javascript-decorators上有多个等效的ES6和ES5示例。

修饰器可以动态地改变函数、方法或类的功能,而无需直接使用子类或更改被修饰函数的源代码。

它们通常用于控制访问、注册和注解。


20

什么是@myDecorator()

在 JavaScript 中,@ 符号代表一个装饰器。装饰器并不存在于 ES6 中,所以你使用的代码中的装饰器可能会被转译成任何浏览器都能运行的版本的 JavaScript。

什么是装饰器?

装饰器可以动态地扩展(即装饰)对象的行为。在运行时添加新行为的能力是通过一个“包裹”原始对象的 Decorator 对象实现的。装饰器不仅仅是 JavaScript 中的概念,它是所有面向对象编程语言中使用的设计模式。以下是维基百科上的定义:

在面向对象编程中,装饰器模式是一种设计模式,它允许在单个对象上动态添加行为,而无需影响来自相同类的其他对象的行为。装饰器模式通常有助于遵循单一职责原则,因为它允许将功能分割在具有独特关注领域的类之间。

为什么要使用装饰器?

使用装饰器可以在运行时修改对象的功能。例如,在你的代码中,你只需导入这个装饰器并将它添加到你的 CounterApp 类中。现在你的 CounterApp 动态地添加了功能而不需要知道实现细节。

例子:

// decorator lights is a function which receives the class as an argument
let lights = function(tree) {
  // The behaviour of the class is modified here
  tree.treeLights = 'Christmas lights'
}

@lights  // the decorator is applied here
class ChristmasTree {}

console.log(ChristmasTree.treeLights);  // logs Christmas lights

1
那么 connect(...)@connect(...) 有什么区别呢? - lmat - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接