Is the underscore prefix for property and method names merely a convention?

224,599

Solution 1

Welcome to 2019!

It appears a proposal to extend class syntax to allow for # prefixed variable to be private was accepted. Chrome 74 ships with this support.

_ prefixed variable names are considered private by convention but are still public.

This syntax tries to be both terse and intuitive, although it's rather different from other programming languages.

Why was the sigil # chosen, among all the Unicode code points?

  • @ was the initial favorite, but it was taken by decorators. TC39 considered swapping decorators and private state sigils, but the committee decided to defer to the existing usage of transpiler users.
  • _ would cause compatibility issues with existing JavaScript code, which has allowed _ at the start of an identifier or (public) property name for a long time.

This proposal reached Stage 3 in July 2017. Since that time, there has been extensive thought and lengthy discussion about various alternatives. In the end, this thought process and continued community engagement led to renewed consensus on the proposal in this repository. Based on that consensus, implementations are moving forward on this proposal.

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

Solution 2

That's only a convention. The Javascript language does not give any special meaning to identifiers starting with underscore characters.

That said, it's quite a useful convention for a language that doesn't support encapsulation out of the box. Although there is no way to prevent someone from abusing your classes' implementations, at least it does clarify your intent, and documents such behavior as being wrong in the first place.

Solution 3

JavaScript actually does support encapsulation, through a method that involves hiding members in closures (Crockford). That said, it's sometimes cumbersome, and the underscore convention is a pretty good convention to use for things that are sort of private, but that you don't actually need to hide.

Solution 4

JSDoc 3 allows you to annotate your functions with the @access private (previously the @private tag) which is also useful for broadcasting your intent to other developers - http://usejsdoc.org/tags-access.html

Solution 5

"Only conventions? Or is there more behind the underscore prefix?"

Apart from privacy conventions, I also wanted to help bring awareness that the underscore prefix is also used for arguments that are dependent on independent arguments, specifically in URI anchor maps. Dependent keys always point to a map.

Example ( from https://github.com/mmikowski/urianchor ) :

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

The URI anchor on the browser search field is changed to:

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

This is a convention used to drive an application state based on hash changes.

Share:
224,599

Related videos on Youtube

Kenny Meyer
Author by

Kenny Meyer

Updated on June 25, 2021

Comments

  • Kenny Meyer
    Kenny Meyer almost 3 years

    Is the underscore prefix in JavaScript only a convention, like for example in Python private class methods are?

    From the 2.7 Python documentation:

    “Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member).

    Does this also apply to JavaScript?

    Take for example this JavaScript code:

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

    Also, underscore prefixed variables are used.

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

    Only conventions? Or is there more behind the underscore prefix?


    I admit my question is quite similar to this question, but it didn't make one smarter about the significance of the underscore prefix in JavaScript.

  • Juho Vepsäläinen
    Juho Vepsäläinen over 13 years
    Yup. Even if the language doesn't "support" it, it's a really handy convention to have.
  • Jason
    Jason almost 13 years
    Up vote for clarifying how to achieve closures, down vote for saying underscores are good convention. So I won't vote either way :)
  • Zach Lysobey
    Zach Lysobey about 11 years
    Hiding members in closures can sometimes hinder testability. Check out this article: adequatelygood.com/2010/7/Writing-Testable-JavaScript
  • Tamás Pap
    Tamás Pap almost 11 years
    @Jason - Just curious, why you consider underscore a bad convention?
  • Jason
    Jason almost 11 years
    @TamasPap - A few reasons, but just my option: 1) A crutch to force JS into a style of other languages 2) If it's accessible, it will be used. The underscore can litter up and convolute outside code. 3) Confusing to new JS programmers.
  • Muhammad Umer
    Muhammad Umer almost 11 years
    Serious prob. jsfiddle.net/VmFSR As you can see there, value created name is only accessible by prefixing new value, created, using _ i'd love to know what's going on!? why it is not this.name instead?
  • Frédéric Hamidi
    Frédéric Hamidi almost 11 years
    @Muhammad Umer, I'm not sure I understand your comment. console.log(someone._name = "Jean Dupont"); works as well as console.log(someone.name);, and it both assigns and evaluates the underscore-prefixed member behind the property. As you can see, theres is no guaranteed encapsulation through underscores :)
  • Muhammad Umer
    Muhammad Umer almost 11 years
    wow i totally missed the part that mere assigning of a value is enough to declare something. My bad. Thanks for pointing out i was going crazy. :D
  • Esailija
    Esailija over 10 years
    @Jason Well obviously private is accessible in all languages, why is that a downside?
  • Kabir Sarin
    Kabir Sarin over 10 years
    Even with a closure, it's still technically possible to gain access to the so called "private" variable. The _convention at least lets devs know to do so at their own risk (or something like that).
  • Vince
    Vince over 9 years
    @KabirSarin technically speaking, how exactly do you access a private variable (var declared in a closure) from outside the closure? It's my understanding that you can't, unless you inherit scope (which you won't, even in methods that are part of the func/object's prototype.
  • Kabir Sarin
    Kabir Sarin over 9 years
    @Sorenly, a hack like this gist.github.com/sarink/7394867 is always possible. you could guard against it in a framework, of course. but if someone can see the source, surely they could figure out a way.
  • trusktr
    trusktr over 9 years
    "... things that are sort of private , but that you don't actually need to hide." ...or things that you'd like to be private, and also inheritable. Variables in closures are not inheritable AFAIK.
  • Frédéric Hamidi
    Frédéric Hamidi over 9 years
    @trusktr, ah, protected then :)
  • trusktr
    trusktr over 9 years
    @FrédéricHamidi Yeah, protected. :D There's no way to do it in JavaScript as far as I know (is there?).
  • foxontherock
    foxontherock over 8 years
    By default, Visual Studio try to help you respect this. The javascript IntelliSense engine show you "private" properties, from inside the object, when using the "this" variable. But, when called from the outside, it hides all underscored attributes.
  • vol7ron
    vol7ron about 8 years
    @Jason if you've ever programmed with many people, you would understand why it's a good convention. Traditionally, it means something is private, but in JavaScript it could also mean, be aware, this could change, so you should probably write your own method/function that may be more stable. What you're trying to avoid (and convey to fellow developers) is that it may change in the future, and you aren't going to maintain it for backwards compatibility; meaning it's up to them to fix their stuff if it breaks their code.
  • vol7ron
    vol7ron about 8 years
    @KabirSarin that example is allowing a person to set a key, which could be called by another method (in this case the key is push). It's more poor programming, than private/public exposure and not something that's always possible. If _array[_array.length]=v was used in append -or- if key validation was used in store preventing the use of push (e.g., if(i!=='push')), it would not be an issue in that example (gist.github.com/sarink/7394867). Private methods can still affect global scoped variables, even in other languages.
  • bvdb
    bvdb over 5 years
    I don't think that import/export offers support for private class methods in any way. I mean, it does support a similar functionality on class level, but it does not offer hiding the contained methods. (i.e. all contained methods are always public)
  • Nicolas Zozol
    Nicolas Zozol over 5 years
    You export the class, and inner function call outside function. These functions are privates.
  • Karuhanga
    Karuhanga almost 5 years
    It appears the language now supports this. See answer below.
  • Kenny Meyer
    Kenny Meyer almost 5 years
    @Karuhanga he answered this back in 2010 - of course things have changed in 10 years