Unterstrichen Sie das Präfix für Eigenschafts- und Methodennamen in JavaScript

240

Ist das Unterstrichpräfix in JavaScript nur eine Konvention, wie sie beispielsweise in Python-Methoden für private Klassen verwendet wird?

Aus der 2.7 Python-Dokumentation:

In Python gibt es keine "privaten" Instanzvariablen, auf die nur innerhalb eines Objekts zugegriffen werden kann. Es gibt jedoch eine Konvention, die von den meisten Python-Codes befolgt wird: Ein Name mit einem Unterstrich (z. B. _spam) sollte als nicht öffentlicher Teil der API behandelt werden (unabhängig davon, ob es sich um eine Funktion, eine Methode oder ein Datenelement handelt). .

Gilt das auch für JavaScript?

Nehmen Sie zum Beispiel diesen JavaScript-Code:

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

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

Außerdem werden Variablen mit Unterstrichen vorangestellt.

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

Nur Konventionen? Oder steckt mehr hinter dem Unterstrich?


Ich gebe zu, dass meine Frage dieser Frage ziemlich ähnlich ist , aber sie hat die Bedeutung des Unterstrichpräfixes in JavaScript nicht klüger gemacht.

Kenny Meyer
quelle

Antworten:

33

Willkommen im Jahr 2019!

Es scheint ein Vorschlag zur Erweiterung der Klassensyntax zu sein, damit die #Variable mit dem Präfix privat sein kann. Chrome 74 Schiffe mit dieser Unterstützung.

_ Präfixvariablennamen werden gemäß Konvention als privat betrachtet, sind jedoch weiterhin öffentlich.

Diese Syntax versucht sowohl knapp als auch intuitiv zu sein, obwohl sie sich von anderen Programmiersprachen unterscheidet.

Warum wurde das Siegel # unter allen Unicode-Codepunkten ausgewählt?

  • @ war der ursprüngliche Favorit, wurde aber von Dekorateuren übernommen. TC39 erwog, Dekorateure und private staatliche Siegel auszutauschen, aber das Komitee beschloss, die bestehende Verwendung von Transpilerbenutzern zu verschieben.
  • _ würde Kompatibilitätsprobleme mit vorhandenem JavaScript-Code verursachen, der _ am Anfang eines Bezeichners oder (öffentlichen) Eigenschaftsnamens für eine lange Zeit erlaubt hat.

Dieser Vorschlag erreichte im Juli 2017 die dritte Stufe. Seitdem wurde ausführlich über verschiedene Alternativen nachgedacht und lange diskutiert. Letztendlich führten dieser Denkprozess und das fortgesetzte Engagement der Gemeinschaft zu einem erneuten Konsens über den Vorschlag in diesem Repository. Auf der Grundlage dieses Konsenses werden die Umsetzungen für diesen Vorschlag vorangetrieben.

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

Karuhanga
quelle
257

Das ist nur eine Konvention. Die Javascript-Sprache gibt Bezeichnern, die mit Unterstrichen beginnen, keine besondere Bedeutung.

Das heißt, es ist eine ziemlich nützliche Konvention für eine Sprache, die keine sofortige Kapselung unterstützt . Obwohl es keine Möglichkeit gibt, jemanden daran zu hindern, die Implementierungen Ihrer Klassen zu missbrauchen, klärt dies zumindest Ihre Absicht und dokumentiert ein solches Verhalten, das in erster Linie falsch ist .

Frédéric Hamidi
quelle
4
Jep. Auch wenn die Sprache es nicht "unterstützt", ist es eine sehr praktische Konvention.
Juho Vepsäläinen
Ernstes Problem. jsfiddle.net/VmFSR Wie Sie dort sehen können, kann auf den Wertschöpfungsnamen nur zugegriffen werden, indem ein neuer Wert vorangestellt wird, der erstellt wurde. _Ich würde gerne wissen, was los ist!? warum ist es nicht this.namestattdessen?
Muhammad Umer
1
@ Muhammad Umer, ich bin mir nicht sicher, ob ich deinen Kommentar verstehe. console.log(someone._name = "Jean Dupont");funktioniert genauso gut wie console.log(someone.name);und weist das Element mit dem Unterstrich vor der Eigenschaft zu und wertet es aus. Wie Sie sehen können , gibt es keine garantierte Einkapselung durch Unterstriche :)
Frédéric Hamidi
3
Standardmäßig versucht Visual Studio, Ihnen dabei zu helfen, dies zu respektieren. Die Javascript-IntelliSense-Engine zeigt Ihnen "private" Eigenschaften innerhalb des Objekts, wenn Sie die Variable "this" verwenden. Wenn es jedoch von außen aufgerufen wird, werden alle unterstrichenen Attribute ausgeblendet.
Foxontherock
1
@ Karuhanga er antwortete dies im Jahr 2010 - natürlich haben sich die Dinge in 10 Jahren geändert
Kenny Meyer
99

JavaScript unterstützt tatsächlich die Kapselung durch eine Methode, bei der Mitglieder in Verschlüssen versteckt werden (Crockford). Das heißt, es ist manchmal umständlich, und der Unter Konvention ist eine ziemlich gute Konvention für Dinge zu verwenden , die Art von privat sind, aber dass Sie nicht wirklich brauchen , sich zu verstecken.

Zach
quelle
19
Nach oben stimmen, um zu klären, wie Schließungen erreicht werden können, nach unten stimmen, um zu sagen, dass Unterstriche eine gute Konvention sind. Also werde ich nicht so oder so abstimmen :)
Jason
3
Das Verstecken von Mitgliedern in Verschlüssen kann manchmal die Testbarkeit beeinträchtigen. Schauen Sie sich diesen Artikel: adequatelygood.com/2010/7/Writing-Testable-JavaScript
Zach Lysobey
4
@ Jason - Nur neugierig, warum Sie eine schlechte Konvention unterstreichen?
Tamás Pap
5
@TamasPap - Ein paar Gründe, aber nur meine Option: 1) Eine Krücke, um JS in einen Stil anderer Sprachen zu zwingen. 2) Wenn es zugänglich ist, wird es verwendet. Der Unterstrich kann außerhalb des Codes liegen und sich verwickeln. 3) Verwirrung bei neuen JS-Programmierern.
Jason
9
Selbst mit einem Abschluss ist es technisch immer noch möglich, auf die sogenannte "private" Variable zuzugreifen. Die _convention lässt Entwickler zumindest wissen, dass sie dies auf eigenes Risiko (oder so ähnlich) tun.
Sarink
14

Mit JSDoc 3 können Sie Ihre Funktionen mit dem @access private(zuvor dem @privateTag) versehen, was auch nützlich ist, um Ihre Absicht an andere Entwickler zu senden - http://usejsdoc.org/tags-access.html

Philrabin
quelle
10

"Nur Konventionen? Oder steckt mehr hinter dem Unterstrich?"

Abgesehen von Datenschutzkonventionen wollte ich auch dazu beitragen, das Bewusstsein dafür zu schärfen, dass das Unterstrichpräfix auch für Argumente verwendet wird, die von unabhängigen Argumenten abhängig sind, insbesondere in URI-Ankerkarten. Abhängige Schlüssel zeigen immer auf eine Karte.

Beispiel (von https://github.com/mmikowski/urianchor ):

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

Der URI-Anker im Browser-Suchfeld wird geändert in:

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

Dies ist eine Konvention, die verwendet wird, um einen Anwendungsstatus basierend auf Hash-Änderungen zu steuern.

Sam Araiza
quelle
8

import/exportmacht jetzt den Job mit ES6. Ich neige immer noch dazu, nicht exportierten Funktionen ein Präfix voranzustellen, _wenn die meisten meiner Funktionen exportiert werden.

Wenn Sie nur eine Klasse exportieren (wie in eckigen Projekten), wird diese überhaupt nicht benötigt.

export class MyOpenClass{

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

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

}

function close(){ /*... this is really private... */ }
Nicolas Zozol
quelle
Ich glaube nicht, dass Import / Export in irgendeiner Weise Unterstützung für private Klassenmethoden bietet. Ich meine, es unterstützt eine ähnliche Funktionalität auf Klassenebene, bietet aber nicht das Ausblenden der enthaltenen Methoden. (dh alle enthaltenen Methoden sind immer öffentlich)
bvdb
Sie exportieren die Klasse und die innere Funktion ruft die äußere Funktion auf. Diese Funktionen sind privat.
Nicolas Zozol