web-dev-qa-db-fra.com

Que fait le symbole at (@) en javascript ES6? (ECMAScript 2015)

Je regarde du code ES6 et je ne comprends pas ce que fait le symbole @ lorsqu'il est placé devant une variable. La chose la plus proche que j'ai pu trouver a quelque chose à voir avec les champs privés?

Code que je regardais de la bibliothèque 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)} />
    );
  }
}

Voici un article de blog que j'ai trouvé sur le sujet: https://github.com/zenparsing/es-private-fields

Dans ce billet de blog, tous les exemples sont dans le contexte d'une classe - qu'est-ce que cela signifie lorsque le symbole est utilisé dans un module?

54
Kevin Wu

C'est un décorateur. C'est une proposition à ajouter à ECMAScript. Il existe plusieurs exemples équivalents ES6 et ES5 sur: javascript-decorators .

Les décorateurs modifient dynamiquement la fonctionnalité d'une fonction, d'une méthode ou d'une classe sans avoir à utiliser directement des sous-classes ou à changer le code source de la fonction en cours de décoration.

Ils sont couramment utilisés pour contrôler l'accès, l'enregistrement, l'annotation.

35
Kit Sunde

J'ai trouvé que la réponse acceptée n'était pas suffisante pour m'aider à trier cela, alors j'ajoute un peu plus de détails pour aider ceux qui trouvent cela.

Le problème est qu'il n'est pas clair exactement quel est le décorateur. Le décorateur dans l'exemple donné n'est pas seulement le @ symbole, c'est le @connect une fonction. Autrement dit, le @connect la fonction est décoration la classe CounterApp.

Et que fait-il dans ce cas? C'est connecter le state.counter valeur pour les accessoires de la classe. N'oubliez pas qu'en redux, la fonction connect prend deux arguments: mapStateToProps et mapDispatchToProps. Dans cet exemple, il ne prend qu'un seul argument - mapStateToProps.

Je n'ai pas trop étudié cela, mais cela semble être un moyen d'encapsuler vos mappages état-à-accessoires et répartition-à-accessoires afin qu'ils accompagnent vos composants plutôt que d'être situés dans un fichier différent.

75
Kryten

Qu'est-ce que @myDecorator()?

Le @ le symbole en javascript représente un décorateur. Les décorateurs ne sont pas présents dans ES6 donc le code in avec lequel vous travaillez avec le décorateur est probablement transposé en une version de javascript qui peut être exécutée dans n'importe quel navigateur.

Qu'est-ce qu'un décorateur?

Un décorateur étend (c.-à-d. Décore) le comportement d'un objet de manière dynamique. La possibilité d'ajouter un nouveau comportement lors de l'exécution est réalisée par un objet Decorator qui "s'enroule" autour de l'objet d'origine. Un décorateur n'est pas seulement un concept en javascript. C'est un modèle de conception utilisé dans tous les langages de programmation orientés objet. Voici une définition de wikipedia:

Dans la programmation orientée objet, le motif décorateur est un motif de conception qui permet d'ajouter un comportement à un objet individuel, dynamiquement, sans affecter le comportement d'autres objets du même classe. Le modèle de décorateur est souvent utile pour adhérer au principe de responsabilité unique, car il permet de diviser la fonctionnalité entre les classes avec des domaines de préoccupation uniques

Pourquoi utiliser un décorateur?

La fonctionnalité d'un objet peut être modifiée lors de l'exécution lors de l'utilisation d'un décorateur. Par exemple, dans votre code, vous avez simplement importé le décorateur et l'avez ajouté à votre classe CounterApp. Maintenant, votre CounterApp a dynamiquement ajouté des fonctionnalités sans que vous connaissiez les détails de l'implémentation.

Exemple:

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