Skip to content

Instantly share code, notes, and snippets.

@rauschma
Last active April 15, 2021 13:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rauschma/a4729faa65b30a6fda46a5799016458a to your computer and use it in GitHub Desktop.
Save rauschma/a4729faa65b30a6fda46a5799016458a to your computer and use it in GitHub Desktop.

Sketch: scoped private fields

So far, private fields are introduced as follows:

class MyClass {
  #privateField = 123;
}

I’d like to propose a small extension: scoped private fields.

Functional style (the proposal)

The following style is becoming popular in the JavaScript world. It benefits from scoped privacy:

private #data;

function createStringBuilder() {
  return {
    #data: '',
  };
}

function add(sb, str) {
  sb.#data += str;
}

function toString(sb) {
  return sb.#data;
}

New in this code:

  • The keyword private in the first line.
  • The ability to use private fields in object literals.

OOP style

As a slight downside, you now always need to use the keyword private:

class StringBuilder {
  private #data = ''; // keyword is required
  add(str) {
    this.#data += str;
  }
  toString() {
    return this.#data;
  }
}

On the upside, this gives you the freedom to widen the scope of privacy:

private #data;

class StringBuilder {
  #data = ''; // no keyword!
  add(str) {
    this.#data += str;
  }
}
function toString(stringBuilder) {
  return stringBuilder.#data;
}

Alternative syntax

Alternative syntax has been proposed:

  • Keyword private not needed for “normal” private fields.
  • Two keywords if you want to widen the scope of privacy: private and outer.

Example:

private #data;

class StringBuilder {
  outer #data = ''; // keyword is now required
  add(str) {
    this.#data += str;
  }
}
function toString(stringBuilder) {
  return stringBuilder.#data;
}

FP example:

private #data;

function createStringBuilder() {
  return {
    outer #data: '', // keyword is now required
  };
}

function add(sb, str) {
  sb.#data += str;
}

function toString(sb) {
  return sb.#data;
}
@ignas2526
Copy link

I disagree with using the # symbol. It is counter-intuitive. Static fields and methods are declared using static keyword. Using private keyword is more intuitive and fits nicely with existing static keyword. Using private keyword is also easier to remember and to read.
It is equally weird that you have to specify that keyword when you access the variable. That also goes against existing conventions.

@devsnowy
Copy link

I would like to know as well as many others why we need a new symbol # when we all know that private only means one thing.
At least add in the specification clearly why private naming was not used in favor of a new character. Makes everyone's life harder to approve such concept for the sake of it.

@jsilvao
Copy link

jsilvao commented Sep 20, 2020

# is blatantly awful, non-intuitive and will only fuel the JavaScript is a flawed language adage (which I have to agree to if this # symbol is introduced). private should be the way to declare private fields. The fact we're having a year-long discussion about this thing is what sometimes makes me question the reliability of the process (and people) upgrading JavaScript. Please, use private.

@rauschma
Copy link
Author

@abiphone
Copy link

abiphone commented Dec 31, 2020

Using # is just awful, it does not follow standard JavaScript declarative syntax. It feels more like a PHP-style declaration (using symbols for declaration, $ for example) than a standard JavaScript-style declaration (using keywords for declaration, let for example).

@yashsway
Copy link

yashsway commented Feb 12, 2021

@rauschma's comment and the FAQ on the proposal make it clear as day to be honest - it makes sense for the language. Yes, it looks ugly at first and not like standard JavaScript style declaration (which uses keywords for everything else), but I think we'll get used to it. On the other hand, I was wondering if during compile time, private field can be mapped over to #field ? I guess that means during access you'll have to remember to use the #, but during declaration it would look different. Not sure if that would be better or not actually, but it seems like a good middle ground?

~ thankful for everything OSS contributors do, and the TC39 committee as well!

@basickarl
Copy link

basickarl commented Apr 13, 2021

wouldn't _ be viable if at the top of the file something tells the compiler that it is reserved so that it doesn't break current functionality, something that is like "use strict"; but for _? # is a horrible solution.

@ljharb
Copy link

ljharb commented Apr 13, 2021

No existing identifier is viable, because var _ = something at the bottom of the file hoists it ti the top, and there could be silent conflicts.

@basickarl
Copy link

basickarl commented Apr 15, 2021

But the whole point of the comment/code at the top was to tell the compiler to act in a specific way? Like bash's #!/usr/bin/env bash, am I missing something?

@ljharb
Copy link

ljharb commented Apr 15, 2021

That would be a new mode (like strict mode), and the committee is pretty firmly against ever adding another one. In addition, the refactoring hazard would be large, as code that works fine in one file would suddenly work differently in another.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment