Sottolineare il prefisso per i nomi di proprietà e metodo in JavaScript


241

Il prefisso di sottolineatura in JavaScript è solo una convenzione, come ad esempio nei metodi di classe privata di Python?

Dalla documentazione 2.7 di Python:

In Python non esistono variabili di istanza "private" a cui non è possibile accedere se non dall'interno di un oggetto. Tuttavia, esiste una convenzione seguita dalla maggior parte del codice Python: un nome preceduto da un carattere di sottolineatura (ad esempio _spam) deve essere trattato come una parte non pubblica dell'API (che si tratti di una funzione, un metodo o un membro di dati) .

Questo vale anche per JavaScript?

Prendi ad esempio questo codice JavaScript:

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

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

Inoltre, vengono utilizzate le variabili con prefisso di sottolineatura.

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

Solo convenzioni? O c'è altro dietro il prefisso di sottolineatura?


Ammetto che la mia domanda è abbastanza simile a questa domanda , ma non ha reso più intelligente il significato del prefisso di sottolineatura in JavaScript.


Risposte:


33

Benvenuti nel 2019!

Sembra che sia stata accettata la proposta di estendere la sintassi della classe per consentire che la #variabile con prefisso sia privata. Chrome 74 viene fornito con questo supporto.

_ i nomi delle variabili con prefisso sono considerati privati ​​per convenzione ma sono ancora pubblici.

Questa sintassi cerca di essere sia concisa che intuitiva, sebbene sia piuttosto diversa dagli altri linguaggi di programmazione.

Perché è stato scelto il sigillo #, tra tutti i punti di codice Unicode?

  • @ era il preferito iniziale, ma è stato preso dai decoratori. TC39 ha preso in considerazione lo scambio di decoratori e sigilli di stato privati, ma il comitato ha deciso di rimandare all'utilizzo esistente degli utenti di transpiler.
  • _ causerebbe problemi di compatibilità con il codice JavaScript esistente, che ha consentito _ all'inizio di un identificatore o di un nome di proprietà (pubblico) da molto tempo.

Questa proposta ha raggiunto la fase 3 a luglio 2017. Da allora, ci sono state molte riflessioni e lunghe discussioni su varie alternative. Alla fine, questo processo di pensiero e il continuo coinvolgimento della comunità hanno portato a un rinnovato consenso sulla proposta in questo repository. Sulla base di tale consenso, le implementazioni stanno avanzando su questa proposta.

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


257

Questa è solo una convenzione. Il linguaggio Javascript non dà alcun significato speciale agli identificatori che iniziano con caratteri di sottolineatura.

Detto questo, è una convenzione abbastanza utile per un linguaggio che non supporta l' incapsulamento fuori dalla scatola. Anche se non c'è modo di impedire a qualcuno di abusare delle implementazioni delle tue classi, almeno chiarisce le tue intenzioni e documenta in primo luogo comportamenti come errati .


4
Sì. Anche se il linguaggio non lo "supporta", è una convenzione davvero utile da avere.
Juho Vepsäläinen,

Prob seria. jsfiddle.net/VmFSR Come puoi vedere, il valore creato è accessibile solo aggiungendo il prefisso nuovo valore, creato, usando _mi piacerebbe sapere cosa sta succedendo !? perché non è this.nameinvece?
Muhammad Umer,

1
@Muhammad Umer, non sono sicuro di aver capito il tuo commento. console.log(someone._name = "Jean Dupont");funziona bene console.log(someone.name);e assegna e valuta il membro con prefisso di sottolineatura dietro la proprietà. Come puoi vedere , non c'è incapsulamento garantito attraverso i trattini bassi :)
Frédéric Hamidi,

3
Per impostazione predefinita, Visual Studio cerca di aiutarti a rispettare questo. Il motore IntelliSense javascript mostra le proprietà "private", dall'interno dell'oggetto, quando si utilizza la variabile "this". Ma, quando viene chiamato dall'esterno, nasconde tutti gli attributi sottolineati.
foxontherock,

1
@Karuhanga ha risposto a questa domanda nel 2010 - ovviamente le cose sono cambiate in 10 anni
Kenny Meyer

99

JavaScript in realtà supporta l'incapsulamento, attraverso un metodo che coinvolge i membri nascosti nelle chiusure (Crockford). Detto questo, a volte è ingombrante e la convenzione di sottolineatura è una convenzione abbastanza buona da usare per cose che sono in qualche modo private, ma che in realtà non è necessario nascondere.


19
Voto positivo per chiarire come ottenere chiusure, voto negativo per dire che i trattini bassi sono una buona convenzione. Quindi non voterò in nessun caso :)
Jason,

3
Nascondere i membri nelle chiusure a volte può ostacolare la testabilità. Dai un'occhiata a questo articolo: adequatelygood.com/2010/7/Writing-Testable-JavaScript
Zach Lysobey

4
@Jason - Solo curioso, perché pensi di sottolineare una cattiva convenzione?
Tamás Pap,

5
@TamasPap - Alcuni motivi, ma solo la mia opzione: 1) Una stampella per forzare JS in uno stile di altre lingue 2) Se è accessibile, verrà utilizzato. Il carattere di sottolineatura può sporcare e contorto il codice esterno. 3) Confusione per i nuovi programmatori JS.
Jason,

9
Anche con una chiusura, è ancora tecnicamente possibile ottenere l'accesso alla cosiddetta variabile "privata". La _convention almeno fa sapere agli sviluppatori di farlo a proprio rischio (o qualcosa del genere).
sarink


10

"Solo convenzioni? O c'è altro dietro il prefisso di sottolineatura?"

Oltre alle convenzioni sulla privacy, volevo anche contribuire a sensibilizzare sul fatto che il prefisso di sottolineatura viene utilizzato anche per argomenti che dipendono da argomenti indipendenti, in particolare nelle mappe di ancoraggio URI. Le chiavi dipendenti indicano sempre una mappa.

Esempio (da https://github.com/mmikowski/urianchor ):

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

L'ancoraggio URI nel campo di ricerca del browser viene modificato in:

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

Questa è una convenzione utilizzata per guidare uno stato dell'applicazione in base alle modifiche dell'hash.


8

import/exportsta facendo il lavoro con ES6. Tendo ancora a anteporre funzioni non esportate con_ se la maggior parte delle mie funzioni viene esportata.

Se esporti solo una classe (come nei progetti angolari), non è affatto necessaria.

export class MyOpenClass{

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

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

}

function close(){ /*... this is really private... */ }

Non credo che import / export offra in alcun modo il supporto per metodi di classe privata. Voglio dire, supporta una funzionalità simile a livello di classe, ma non offre nascondere i metodi contenuti. (cioè tutti i metodi contenuti sono sempre pubblici)
bvdb

Si esporta la classe e la funzione interna chiama la funzione esterna. Queste funzioni sono private.
Nicolas Zozol,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.