What does the at symbol (@) do in ES6 javascript? (ECMAScript 2015)

I'm looking at some ES6 code and I don't understand what the @ symbol does when it is placed in front of a variable. The closest thing I could find has something to do with private fields?

Code I was looking at from the redux library:

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)} />
    );
  }
}

Here is a blog post I found on the topic: https://github.com/zenparsing/es-private-fields

In this blog post all the examples are in the context of a class - what does it mean when the symbol is used within a module?

Answers:

Answer

It's a decorator. It's a proposal to be added to ECMAScript. There are multiple ES6 and ES5 equivalent examples on: javascript-decorators.

Decorators dynamically alter the functionality of a function, method, or class without having to directly use subclasses or change the source code of the function being decorated.

They are commonly used to control access, registration, annotation.

Answer

I found the accepted answer was not enough to help me sort this out, so I'm adding a little more detail to help others who find this.

The problem is that it's unclear exactly what is the decorator. The decorator in the example given is not just the @ symbol, it's the @connect function. Simply put, the @connect function is decorating the CounterApp class.

And what is it doing in this case? It's connecting the state.counter value to the props of the class. Remember that in redux the connect function takes two arguments: mapStateToProps and mapDispatchToProps. In this example, it's taking only one argument - mapStateToProps.

I haven't investigated this too much, but this appears to be a way to encapsulate your state-to-props and dispatch-to-props mappings so they accompany your components rather than being located in a different file.

Answer

What is @myDecorator()?

The @ symbol in javascript stands for a decorator. Decorators are not present in ES6 so the in code you are working with the decorator is probably transpiled to an version of javascript which can be run in any browser.

What is a decorator?

A decorator extends (i.e. decorates) an object’s behavior dynamically. The ability to add new behavior at runtime is accomplished by a Decorator object which ‘wraps itself’ around the original object. A decorator is not just a concept in javascript. It is a design pattern used in all object oriented programming languages. Here is a definition from wikipedia:

In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern

Why use a decorator?

The functionality of an object can be modified at runtime when using a decorator. For example, in your code you simply imported the decorator and added it to your CounterApp class. Now your CounterApp has dynamically added functionality Without you knowing the implementation details.

Example:

// 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

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.