Souligner le préfixe des noms de propriété et de méthode en JavaScript

241

Le préfixe de soulignement en JavaScript n'est-il qu'une convention, comme par exemple dans les méthodes de classe privée Python?

De la documentation 2.7 Python:

Les variables d'instance «privées» auxquelles on ne peut accéder que depuis l'intérieur d'un objet n'existent pas en Python. Cependant, il existe une convention qui est suivie par la plupart du code Python: un nom préfixé avec un trait de soulignement (par exemple _spam) doit être traité comme une partie non publique de l'API (qu'il s'agisse d'une fonction, d'une méthode ou d'un membre de données) .

Est-ce que cela s'applique également à JavaScript?

Prenons par exemple ce code JavaScript:

function AltTabPopup() {
    this._init();
}

AltTabPopup.prototype = {
    _init : function() {
        ...
    }
}

En outre, des variables préfixées de soulignement sont utilisées.

    ...
    this._currentApp = 0;
    this._currentWindow = -1;
    this._thumbnailTimeoutId = 0;
    this._motionTimeoutId = 0;
    ...

Seules les conventions? Ou y a-t-il plus derrière le préfixe de soulignement?


J'admets que ma question est assez similaire à cette question , mais cela n'a pas rendu plus intelligent la signification du préfixe de soulignement dans JavaScript.

Kenny Meyer
la source
Voir également stackoverflow.com/questions/17359885/…
Jon Onstott

Réponses:

33

Bienvenue en 2019!

Il semble qu'une proposition visant à étendre la syntaxe des classes afin de permettre aux #variables préfixées d'être privées a été acceptée. Chrome 74 est livré avec ce support.

_ Les noms de variable préfixés sont considérés comme privés par convention mais restent publics.

Cette syntaxe essaie d'être à la fois concise et intuitive, bien qu'elle soit plutôt différente des autres langages de programmation.

Pourquoi le sigil # a-t-il été choisi, parmi tous les points de code Unicode?

  • @ était le favori initial, mais il a été pris par les décorateurs. TC39 a envisagé d'échanger des décorateurs et des sceaux d'État privés, mais le comité a décidé de s'en remettre à l'utilisation actuelle des utilisateurs de transpilateurs.
  • _ causerait des problèmes de compatibilité avec le code JavaScript existant, ce qui a permis _ au début d'un identifiant ou d'un nom de propriété (public) pendant longtemps.

Cette proposition est parvenue à l'étape 3 en juillet 2017. Depuis lors, il y a eu une réflexion approfondie et de longues discussions sur les différentes alternatives. En fin de compte, ce processus de réflexion et l'engagement continu de la communauté ont conduit à un consensus renouvelé sur la proposition dans ce référentiel. Sur la base de ce consensus, les mises en œuvre progressent sur cette proposition.

Voir https://caniuse.com/#feat=mdn-javascript_classes_private_class_fields

Karuhanga
la source
257

Ce n'est qu'une convention. Le langage Javascript ne donne aucune signification particulière aux identifiants commençant par des caractères de soulignement.

Cela dit, c'est une convention assez utile pour un langage qui ne prend pas en charge l' encapsulation hors de la boîte. Bien qu'il n'y ait aucun moyen d'empêcher quelqu'un d'abuser des implémentations de vos classes, au moins cela clarifie votre intention et documente un tel comportement comme étant mauvais en premier lieu.

Frédéric Hamidi
la source
4
Ouaip. Même si le langage ne le "supporte" pas, c'est une convention très pratique à avoir.
Juho Vepsäläinen
Prob sérieux. jsfiddle.net/VmFSR Comme vous pouvez le voir, le nom de la valeur créée n'est accessible qu'en préfixant la nouvelle valeur, créée, en utilisant _j'aimerais savoir ce qui se passe!? pourquoi pas à la this.nameplace?
Muhammad Umer
1
@Muhammad Umer, je ne suis pas sûr de comprendre votre commentaire. console.log(someone._name = "Jean Dupont");fonctionne aussi bien que console.log(someone.name);, et il attribue et évalue à la fois le membre avec préfixe de soulignement derrière la propriété. Comme vous pouvez le voir , il n'y a pas d'encapsulation garantie par des traits de soulignement :)
Frédéric Hamidi
3
Par défaut, Visual Studio essaie de vous aider à respecter cela. Le moteur javascript IntelliSense vous montre des propriétés "privées", de l'intérieur de l'objet, lorsque vous utilisez la variable "this". Mais, lorsqu'il est appelé de l'extérieur, il masque tous les attributs soulignés.
foxontherock
1
@Karuhanga, il a répondu à cela en 2010 - bien sûr, les choses ont changé en 10 ans
Kenny Meyer
99

JavaScript prend en charge l'encapsulation, grâce à une méthode qui implique de masquer les membres dans les fermetures (Crockford). Cela dit, c'est parfois lourd, et la convention de soulignement est une assez bonne convention à utiliser pour des choses qui sont en quelque sorte privées, mais que vous n'avez pas vraiment besoin de cacher.

Zach
la source
19
Votez pour clarifier comment réaliser les fermetures, votez pour dire que les soulignés sont une bonne convention. Je ne voterai donc pas de toute façon :)
Jason
3
Cacher des membres dans des fermetures peut parfois entraver la testabilité. Consultez cet article: adequatelygood.com/2010/7/Writing-Testable-JavaScript
Zach Lysobey
4
@Jason - Juste curieux, pourquoi vous considérez souligner une mauvaise convention?
Tamás Pap
5
@TamasPap - Quelques raisons, mais juste mon option: 1) Une béquille pour forcer JS dans un style d'autres langues 2) Si elle est accessible, elle sera utilisée. Le trait de soulignement peut joncher et alambiquer le code extérieur. 3) Confus aux nouveaux programmeurs JS.
Jason
9
Même avec une fermeture, il est toujours techniquement possible d'accéder à la variable dite "privée". La _convention permet au moins aux développeurs de le faire à leurs propres risques (ou quelque chose comme ça).
Sarink
14

JSDoc 3 vous permet d'annoter vos fonctions avec le @access private(précédemment le @privatetag) qui est également utile pour diffuser votre intention à d'autres développeurs - http://usejsdoc.org/tags-access.html

philrabin
la source
10

"Seulement des conventions? Ou y a-t-il plus derrière le préfixe de soulignement?"

Outre les conventions de confidentialité, je voulais également aider à faire prendre conscience que le préfixe de soulignement est également utilisé pour les arguments qui dépendent d'arguments indépendants, en particulier dans les cartes d'ancrage URI. Les clés dépendantes pointent toujours vers une carte.

Exemple (sur https://github.com/mmikowski/urianchor ):

$.uriAnchor.setAnchor({
  page   : 'profile',
  _page  : {
    uname   : 'wendy',
    online  : 'today'
  }
});

L'ancre URI du champ de recherche du navigateur est remplacée par:

\#!page=profile:uname,wendy|online,today

Il s'agit d'une convention utilisée pour piloter un état d'application basé sur des modifications de hachage.

Sam Araiza
la source
8

import/exportfait maintenant le travail avec ES6. J'ai toujours tendance à préfixer les fonctions non exportées avec _si la plupart de mes fonctions sont exportées.

Si vous exportez uniquement une classe (comme dans les projets angulaires), ce n'est pas du tout nécessaire.

export class MyOpenClass{

    open(){
         doStuff()
         this._privateStuff()
         return close();
    }

    _privateStuff() { /* _ only as a convention */} 

}

function close(){ /*... this is really private... */ }
Nicolas Zozol
la source
Je ne pense pas que l'import / export offre une prise en charge des méthodes de classe privées en aucune façon. Je veux dire, il prend en charge une fonctionnalité similaire au niveau de la classe, mais il ne propose pas de masquer les méthodes contenues. (c'est-à-dire que toutes les méthodes contenues sont toujours publiques)
bvdb
Vous exportez la classe et la fonction interne appelle la fonction externe. Ces fonctions sont privées.
Nicolas Zozol