Subrayar prefijo para nombres de propiedades y métodos en JavaScript

241

¿El prefijo de subrayado en JavaScript es solo una convención, como por ejemplo en Python los métodos de clase privada son?

De la documentación de 2.7 Python:

Las variables de instancia "privadas" a las que no se puede acceder, excepto desde dentro de un objeto, no existen en Python. Sin embargo, hay una convención seguida por la mayoría del código de Python: un nombre con un guión bajo (por ejemplo, _spam) debe tratarse como una parte no pública de la API (ya sea una función, un método o un miembro de datos) .

¿Esto también se aplica a JavaScript?

Tome por ejemplo este código JavaScript:

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

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

Además, se utilizan las variables prefijadas de subrayado.

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

¿Solo convenciones? ¿O hay más detrás del prefijo de subrayado?


Admito que mi pregunta es bastante similar a esta pregunta , pero no lo hizo más inteligente sobre la importancia del prefijo de subrayado en JavaScript.

Kenny Meyer
fuente
Ver también stackoverflow.com/questions/17359885/…
Jon Onstott

Respuestas:

33

¡Bienvenido a 2019!

Parece que se aceptó una propuesta para extender la sintaxis de clase para permitir que la #variable prefijada sea privada. Chrome 74 se envía con este soporte.

_ Los nombres de las variables prefijadas se consideran privados por convención, pero siguen siendo públicos.

Esta sintaxis trata de ser breve e intuitiva, aunque es bastante diferente de otros lenguajes de programación.

¿Por qué se eligió el número de sigilo, entre todos los puntos de código Unicode?

  • @ fue el favorito inicial, pero lo tomaron los decoradores. TC39 consideró intercambiar decoradores y sigilos privados del estado, pero el comité decidió diferir el uso existente de los usuarios de transpiladores.
  • _ causaría problemas de compatibilidad con el código JavaScript existente, lo que ha permitido _ al comienzo de un identificador o nombre de propiedad (público) durante mucho tiempo.

Esta propuesta llegó a la Etapa 3 en julio de 2017. Desde entonces, ha habido una amplia reflexión y una larga discusión sobre varias alternativas. Al final, este proceso de pensamiento y el compromiso continuo de la comunidad llevaron a un consenso renovado sobre la propuesta en este repositorio. En base a ese consenso, las implementaciones están avanzando en esta propuesta.

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

Karuhanga
fuente
257

Eso es solo una convención. El lenguaje Javascript no otorga ningún significado especial a los identificadores que comienzan con caracteres de subrayado.

Dicho esto, es una convención bastante útil para un lenguaje que no admite la encapsulación lista para usar. Aunque no hay forma de evitar que alguien abuse de las implementaciones de sus clases, al menos aclara su intención y documenta tales comportamientos como incorrectos en primer lugar.

Frédéric Hamidi
fuente
44
Sip. Incluso si el lenguaje no lo "soporta", es una convención realmente útil.
Juho Vepsäläinen
Prob serio jsfiddle.net/VmFSR Como puede ver allí, solo se puede acceder al nombre del valor creado al prefijar el nuevo valor, creado, usando ¡ _me encantaría saber qué está pasando! ¿Por qué no es en su this.namelugar?
Muhammad Umer
1
@ Muhammad Umer, no estoy seguro de entender tu comentario. console.log(someone._name = "Jean Dupont");funciona tan bien como console.log(someone.name);, y asigna y evalúa el miembro con guión bajo de la propiedad. Como puede ver , no hay una encapsulación garantizada a través de guiones bajos :)
Frédéric Hamidi
3
De forma predeterminada, Visual Studio intenta ayudarte a respetar esto. El motor JavaScript IntelliSense le muestra propiedades "privadas", desde el interior del objeto, cuando utiliza la variable "this". Pero, cuando se llama desde afuera, oculta todos los atributos subrayados.
foxontherock
1
@Karuhanga respondió esto en 2010 - por supuesto, las cosas han cambiado en 10 años
Kenny Meyer
99

JavaScript en realidad admite la encapsulación, a través de un método que consiste en ocultar miembros en cierres (Crockford). Dicho esto, a veces es engorroso, y la convención de subrayado es una convención bastante buena para usar en cosas que son algo privadas, pero que en realidad no necesitas ocultar.

Zach
fuente
19
Un voto positivo para aclarar cómo lograr cierres, un voto negativo para decir que los guiones bajos son una buena convención. Así que no votaré de ninguna manera :)
Jason
3
Ocultar miembros en los cierres a veces puede dificultar la capacidad de prueba. Echa un vistazo a este artículo: adecuadamentetelygood.com/2010/7/Writing-Testable-JavaScript
Zach Lysobey
44
@ Jason - Solo por curiosidad, ¿por qué considera que subrayar es una mala convención?
Tamás Pap
55
@TamasPap: algunas razones, pero solo mi opción: 1) Una muleta para forzar a JS a un estilo de otros idiomas 2) Si es accesible, se usará. El guión bajo puede ensuciarse y convolucionar el código externo. 3) Confuso para los nuevos programadores de JS.
Jason
99
Incluso con un cierre, todavía es técnicamente posible obtener acceso a la llamada variable "privada". La convención _ al menos les permite a los desarrolladores saber que lo hacen bajo su propio riesgo (o algo así).
sarink
14

JSDoc 3 le permite anotar sus funciones con @access private(anteriormente la @privateetiqueta) que también es útil para transmitir su intención a otros desarrolladores: http://usejsdoc.org/tags-access.html

philrabin
fuente
10

"¿Solo convenciones? ¿O hay más detrás del prefijo de subrayado?"

Además de las convenciones de privacidad, también quería ayudar a crear conciencia de que el prefijo de subrayado también se usa para argumentos que dependen de argumentos independientes, específicamente en los mapas de anclaje de URI. Las teclas dependientes siempre apuntan a un mapa.

Ejemplo (de https://github.com/mmikowski/urianchor ):

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

El ancla URI en el campo de búsqueda del navegador se cambia a:

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

Esta es una convención utilizada para controlar el estado de una aplicación basada en cambios hash.

Sam Araiza
fuente
8

import/exportahora está haciendo el trabajo con ES6. Todavía tiendo a prefijar funciones no exportadas con_ si la mayoría de mis funciones se exportan.

Si exporta solo una clase (como en proyectos angulares), no es necesario en absoluto.

export class MyOpenClass{

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

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

}

function close(){ /*... this is really private... */ }
Nicolas Zozol
fuente
No creo que la importación / exportación ofrezca soporte para métodos de clase privada de ninguna manera. Quiero decir, admite una funcionalidad similar a nivel de clase, pero no ofrece ocultar los métodos contenidos. (es decir, todos los métodos contenidos son siempre públicos)
bvdb
Exporta la clase y la función interna llama a la función externa. Estas funciones son privadas.
Nicolas Zozol