Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Please do not use "#" #77

Closed
babakness opened this issue Jan 27, 2018 · 97 comments
Closed

Please do not use "#" #77

babakness opened this issue Jan 27, 2018 · 97 comments

Comments

@babakness
Copy link

babakness commented Jan 27, 2018

Two reasons taste and utility.

  1. Taste: "Reason is the slave of passion" - Hume.

So I confess that to me, this is just straight up ugly. Can there be something other than the '#' character? Why not just a keyword

class {
  whatever x = 5
}

Where "whatever" is a clean word that anyone reading would understand and is also not painful to the eyes.

  1. Utility. There could be a really awesome use of "#" in the future, lets not throw away that opportunity here.
@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

Please read the FAQ; you'll hopefully see why no keyword is feasible.

As for your personal taste; "ugly" is subjective, and many don't find it ugly.

@babakness
Copy link
Author

Ok, subjectivity aside, # could have great potential for something in the future. Its a very assessable character. Right there above the middle finger.

This is an edge case concern. I can appreciate the need to have truly private attributes. Why not ### instead of # given the far reaching concerns and utility a single # can offer.

@babakness
Copy link
Author

babakness commented Jan 27, 2018

Consider, for example, that # in Scala is used for accessing nested classes. My point is that it is important to really consider the future of the language the ergonomics that are being forfeited. The FAQ is also full of opinions, for example, it is stated that this is confusing. I disagree, it is merely an implicit parameter rather than explicit as it is in python (self). Furthermore this is Javascript, it's a necessary learning curve.

I have to admit that having a this.bar inside of class and not a function is confusing in that prototypes are kind of masquerading as classes. Here, this isn't an implicit parameter, so yeah, its confusing.

This need for # is suspicious however. It feel that there is this supposed pressing need for the world that a keyword is just going to really slow things down. Why? Couldn't it be argued that a keyword could become # behind the scenes? So therefore # could really be anything, ###, or whatever.

A keyword is plausible. It is clearer, easier to read, easier to teach, and better to look than a misplaced # tattoo.

@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

A keyword used for declaration that is not also used for access won’t work (per the FAQ).

Do you have another single-character syntactic suggestion besides #? Multiple chars would just make this important feature (way more important than accessing nested classes, for example) less ergonomic.

@babakness
Copy link
Author

babakness commented Jan 27, 2018

Imagine if async/await was paired with symbols instead. Let's say #% and #$; so that one might write #%*function() { const foo = #$ bar() } or if the setters and getters were done using bizarre symbolic contraptions.

Of course keywords are better. A keyword for generators would have been even better. What follows is actual Perl code.

($l=join("",<>))=~s/.*\n/index($`,$&)>=$[||print$&/ge;

Let's stop making Javascript a write-only language. Adding these kinds of symbols is damaging to be sure. Perl went down this "developer ergonomics" rabbit hole. The aftermath of Perl attracted many to following wisdom

https://www.python.org/dev/peps/pep-0020/

# as proposed here is not easy to read, not easy to explain, not explicit, and inconsistent. In fact the problem the FAQ mentions about this are because it is implicit rather than explicit. The implicit behavior of this makes it difficult to teach. It is therefore ironic that # is suggested instead.

class Foo {
   const private bar = 5
   let private baz = 6
   method() {
     console.log( private bar)
     private baz = 7
     // private bar = 8 throws exception (const)
   }
}

What's wrong with that?

@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

It doesn’t allow you to access private values on other objects besides this.

I’d really suggest rereading the FAQ; all of your reasoning is sound, but seems to be missing some of the constraints.

@babakness
Copy link
Author

I see this in the FAQ

this is already a source of enough confusion in JS; we'd prefer not to make it worse. Also, it's a major refactoring hazard: it would be surprising if this.x had different semantics from const thiz = this; thiz.x.

This also wouldn't allow accessing fields of objects other than this.

Those words are there just hanging around, no examples. Please explain and amend the FAQ to state the issue clearly with code so that one can reason about what exactly is the problem. Thanks.

@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

Here's an incredibly necessary and common example:

class Array {
  #arrayData = [];

  static isArray(obj) {
    if (!obj) { return; }
    try {
      return !!obj.#arrayData;
    } catch {
      return false;
    }
  }
}

Here's another:

let i;
class Foo {
  #id = i++;

  compare(other) {
    return other && this.#id === other.#id;
  }
}

@babakness
Copy link
Author

function getFooClass () {
  let internalParameter = 'bookkeeping'
  let totalMembers = 0
  let prototype
  const Foo = function Foo() {
    prototype.totalMembers = ++totalMembers
    Object.defineProperty(this, 'totalMembers', {
      get: function() { return totalMembers },
      set: function() { throw 'read only' }
    });
  }
  prototype = Foo.prototype
  return Foo
}


const Foo = getFooClass()
const a = new Foo()
const b = new Foo()

a.totalMembers
// 2
b.totalMembers
// 2
Foo.prototype.totalMembers
// 2
a.totalMembers = 3
// read only

Is this roughly what you are communicating? Please clarify.

Note that internalParameter is not accessible at all from the outside and totalMembers is available from the outside to read only, but it can be changed from the inside. Also the entire thing about making Foo.prototype.totalMembers accessible can also be removed, obviously, so its just

function getFooClass () {
  let internalParameter = 'bookkeeping'
  let totalMembers = 0
  let prototype
  class Foo {
    constructor(){
      ++totalMembers
      Object.defineProperty(this, 'totalMembers', {
        get: function() { return totalMembers },
        set: function() { throw 'read only' }
      });  
    }
  }
  prototype = Foo.prototype
  return Foo
}

const Foo = getFooClass()
a = new Foo()
b = new Foo()

... or it can be made available to Foo but read only. Or not at all readable. Or we can return from getFooClass both the Foo class (prototype really) and a utility object that gives us stats, etc.

@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

Your "totalMembers" example is what would be a static private; my examples use a static method to read instance private fields off of multiple objects.

@babakness
Copy link
Author

The above with the additional constraint that it would not be intended as an API... is that correct? I'm asking so I can clarify the problem to myself

@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

I'm not sure what you mean by "intended as an API"?

@babakness
Copy link
Author

OK, I better understand now, thanks--I'll think it over for a while because there needs to be something better than wasting # for this purpose... not everyone even likes the class pattern let alone wants forfeit other potential utility of the symbol in the future.

Seriously if we are at a point where all other symbols are exhausted, extinguishing the last of the symbols from this endangered species is unwise. At least the # should be used where all programming styles would benefit. Consider for example the proposed |> operator.

https://github.com/tc39/proposal-pipeline-operator

Its great and all breed of programmers benefit from it. From different skill levels to different philosophies. And that's two characters while far more useful for day-to-day programming.

For now however, shouldn't there be a let or const declared to state if this can or can't be re-assigned? Seems more consistent.

@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

It’s a field, not a variable.

@babakness
Copy link
Author

Here you go

const privateStuff = {}
const initPrivateStuff = function(instance) {
  privateStuff[instance.id] = {
    data: []
  }
}

class Foo {
  static isFoo(obj){
    if(obj && obj.id){
      return privateStuff[obj.id] != null ? true : false
    } else {
      return false
    }
  }
  constructor(){
    this.id = Symbol()
    initPrivateStuff(this)
  }
}

const foo = new Foo()
const bar = new Foo()

console.log(Foo.isFoo(bar))
//true
console.log(Foo.isFoo(foo))
//true

If I understand the issue correctly, please consider if your objections are more valuable than forfeiting # from scenarios that better benefit the community along with all other sound objections again # (lack of readability, inconsistency with the actual language, teachability, cryptic, etc.)

@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

(To be clear: # would be unacceptable for me in pipeline even if nothing else was using it)

And yes, i think instance private is so massively important that even if it killed every future syntax proposal forever, it would be worth it. Just to be clear. (I personally find # here quite readable; there’s nothing like this in the language to maintain consistency with; i think it’s trivially teachable; etc)

@babakness
Copy link
Author

babakness commented Jan 28, 2018

(To be clear: # would be unacceptable for me in pipeline even if nothing else was using it)

Disagree, but # would be a stupid syntax for that too.

And yes, i think instance private is so massively important that even if it killed every future syntax proposal forever, it would be worth it.

Given the remark about the future, fervor here is so high as to be unreasonable and pertinaciously obstinate.

Just to be clear. (I personally find # here quite readable; there’s nothing like this in the language to maintain consistency with; i think it’s trivially teachable; etc)

Strongly disagree.

What problems does # solve here not easily address by my (possible more portable) example? That said it is valid to make the language more ergonomic with measure cost benefits.

I personally feel JavaScript should grow its functional abilities. Its fine for classes to get better too, why not? People who don't like it can not use it. Done.

But I a strongly disagree that this pattern is so important as to deserve the only remaining symbol. No way.

https://stackoverflow.com/questions/2078978/functional-programming-vs-object-oriented-programming

https://blog.learningtree.com/functional-programming-object-orientated-programming/

PLEASE DO NOT STEAL #

Not for an offshoot feature in the OO pattern some might choose to avoid. No.

@babakness
Copy link
Author

babakness commented Jan 28, 2018

Using the example provided above

class Array {
  #arrayData = [];
  #example = 'test'
  static isArray(obj) {
    if (!obj) { return; }
    try {
      return !!obj.#arrayData;
    } catch {
      return false;
    }
  }
  method() {
    console.log(#arrayData)
    // mutation
    #arrayData.push(' :-( ')
    #example = 'something else' 
  }
}

Let's say there is some function private available within functions/class instantiated by new or Object.create that is a more elaborate production of the initPrivateStuff above. Private is essentially inside an implicit closure and has access to a specific instances private fields.

From here we have the syntax sugar such that private as a keyword de-sugars into the funciton

class Array {
  private arrayData = [] // de-sugars to private(this, 'arrayData', [])
  private example = 'test' // de-sugars to private(this, 'example', 'test')
  static isArray(obj) {
    if (!obj) { return; }
    try {
      return !! private(obj,'arrayData') // no sugar, however, for sugar `this` can be bound to something else
    } catch {
      return false;
    }
  }

  method() {
    console.log(private arrayData) // de-sugars to private( this,'arrayData' )
    private arrayData.push('  :-D ') // de-sugars to private( this,'arrayData' ).push(' :-D ')
    private example = 'something else' // de-sugars to private( this,'example', 'something else' )
  }
}

Or something along these lines... private is not available where private is already defined. Just like anything new in ES6. For example, Array.prototype.includes could already be overwritten by some library, and that's fine. There are versions of old JavaScript where super is not a reserved keyword.

Wouldn't this address the aforementioned concerns? It is also explicit and readable using words rather than any strange syntax using #.

In other words, # is replaced by a function private which has syntax sugar to be expressed using keyword where appropriate.

@babakness
Copy link
Author

Added benefits to using private and the private keyword:

  1. Portability.
// magic-library.js
export const external = function(privateFn){
  privateFn(this, ... cool stuff.. )
  ... // more cool stuff
  return whatever
}

// foo.js

import {external} from 'magic-library'

class Foo {
  method() {
    return external.call(this,private)
  }
}
  1. Readability. The keyword private is pretty self explanatory.
  2. Future proof. JavaScript doesn't sacrifice # for this philosophy of OO
  3. Teachable. Understanding this is important in JS. The concept of a private function and they sugar around private is as easy to understand once you understand why the super is there only within a constructor. Likewise private is there for classes and you can reproduce the behavior with prototype as aforementioned.

@doodadjs
Copy link

doodadjs commented Jan 28, 2018

@babakness Your opinion against OO has nothing to do with that proposal. And FP is surely not the only way you go to develop a full computer software. But, like you, I'm on favor to use a keyword for the private scope instead of "#".

@babakness
Copy link
Author

@doodadjs You're misreading. I use OO as well. However, anyone who would benefit from a better use of # has an opinion made relevant to this proposal by its use of #. Anyway, I read from your comment that you like OO a lot and still don't like # as used here. Good! 🤙

I'm offering help in straightening this out, so please first review this and see if it covers the use case where this proposal wants to take away #

#77 (comment)

If so, see how this alternate syntax might be suited or offer insight in making it work.

#77 (comment)

What do think?

I feel that some of those who want # used here are not trying to constructively solve the issue and just want to derail everything to get # used for this purpose. I appreciate your constructive help.

@ljharb
Copy link
Member

ljharb commented Jan 28, 2018

It’s not “taking away” a token, it’s using one. “There might be a proposal in the future” is not a good reason to hamstring an existing proposal.

Do you have a concrete suggestion for a better use of #?

@doodadjs
Copy link

doodadjs commented Jan 29, 2018

@babakness, @ljharb I really prefer the following structure :

class Foo {
  private user = 'doodadjs', // secret
  private password= 'doodadjs2018', // secret
  getList() {
    return window.fetch(`https://api.mycomain.com/foo/list?user=${this.user}&password=${this.password}`);
  }
}

const o = new Foo();
console.log(o.user); // access denied
console.log(o.password); // access denied

But because "o" is just an object with "proto" set to Foo.prototype, I'm thinking that it should still be possible to do :

o.user = 'mario';
o.password = 'mariobros';

To prevent this, may I suggest that the author of 'Foo' should do something like :

class Foo {
  @writable(false), @configurable(false)
  private user = 'doodadjs', // secret
  @writable(false), @configurable(false)
  private password= 'doodadjs2018', // secret
  getList() {
    return window.fetch(`https://api.mycomain.com/foo/list?user=${this.user}&password=${this.password}`);
  }
}

@babakness
Copy link
Author

@ljharb Do I have a concrete suggestion for # today, no. Does this proposal have a good use for it? No.

Yes it is perfectly valid to not allow JS to be disqualified from the benefits of having a highly accessible # in place.

I've made a suggestion above, you not address that. You're not being constructive. There is this fixation on using#, not sure why. What's wrong with the suggestion above? private makes so much more sense and I've even suggested a way of accessing private field on other objects.

@babakness
Copy link
Author

@doodadjs In case I missed it, how do you access private fields on other objects? See @ljharb example and my suggestion as well.

@doodadjs
Copy link

doodadjs commented Jan 29, 2018

@babakness Private fields are private to the methods in their definition(1). I did an implementation of PRIVATE in doodad-js.

(1) "definition" being Foo and Foo.prototype combined.

(Sorry if I use the wrong terms)

EDIT: No... (1) should be : the class definition, sorry

@bakkot
Copy link
Contributor

bakkot commented Jan 29, 2018

@babakness re: private arrayData for access: variations on this syntax have been raised and rejected several times before, including at least once or twice in the main syntax discussion thread and I think once or twice in other random threads. I don't have it in me to track them all down right now, but among other concerns, it doesn't play well with nested property access (e.g. what's the equivalent of this.#next.#data.type?).

To be clear, we've discussed this and alternative syntaxes at extreme length over several years, and the more general discussion of private fields in JS goes back to at least 1999. We are aware that some members of the community find this syntax distasteful, but we can't constantly keep rehashing the same variations on the same several dozen alternative syntax proposals.

@doodadjs
Copy link

@bakkot That's not just distasteful for me, but has a non-sense... Why scoping with special characters like '#' instead of a keyword like 'private'. That's weird, no ?

@doodadjs
Copy link

@bakkot What did you reserved for "protected" and "friend" and others ?

@bakkot
Copy link
Contributor

bakkot commented Jan 29, 2018

@doodadjs The language reserved a number of keywords a long time ago, well before we had an idea of how or whether we'd use them, because we thought we might later use them for features which had not yet been designed. package is similarly reserved, but the ultimate syntax for the module system did not end up using that keyword. It happens.

@babakness
Copy link
Author

@bakkot

class Foo {
  thing = 4
  constructor(){
    console.log(this['thing'])
    console.log(this['#'])
    console.log(this['#foo'])
  }
}

Foo.prototype['#'] = 'surprise'


const myCallback = (hastag) => console.log('outside',hastag)

Object.defineProperty(
  Foo.prototype, 
  '#foo', 
  { get: function() { myCallback(this[`#`]); return this['#']+'!' } }
)

const bar = new Foo()

@bakkot
Copy link
Contributor

bakkot commented Feb 1, 2018

It's true that this['#foo'] is legal. But this.#foo is not. Giving semantics to this.#foo would not break any existing code.

@babakness
Copy link
Author

@bakkot You are saying that this.#foo would mean something different than this['#foo']? @ljharb You are cool with this?!!?

@bakkot
Copy link
Contributor

bakkot commented Feb 1, 2018

@babakness
Copy link
Author

babakness commented Feb 1, 2018

Wow. Super inconsistent. So why not a private function instead, introduced in the class like super. The first parameter is the instance, the second the requested field.

@babakness
Copy link
Author

@bakkot forgot to tag you above.

So why not a private function instead, introduced in the class like super. The first parameter is the instance, the second the requested field.

Also, what about dynamically looking up private fields? Introduce yet another syntax?

@bakkot
Copy link
Contributor

bakkot commented Feb 1, 2018

@babakness Because it would be sufficiently unergonomic as to make the whole feature not worth adding. I realize you don't agree with this, and at this point I doubt I will be able to convince you of it, but the committee has been convinced of it.

Also, what about dynamically looking up private fields? Introduce yet another syntax?

There is no current proposal to allow dynamically looking up private fields, and I am not currently convinced one is warranted.

@babakness
Copy link
Author

babakness commented Feb 1, 2018

@bakkot

Ah, but the private function has sugar consistent with what most people who don't like # want.

class {
  private field = 'foobar'
}

is sugar for some function private

class {
  private(...)
}

Where you only reach for that function in the two lines of code where you want to check the field on other objects. If that is unergonomic, how does one will to declare or use any functions at all?

It seems that these are the problems with the private fields aspect of this proposal:

  • Altering the consistency of the language this.#foo !== this['#foo']
  • Using up the most convenient symbol left not allowing future use of it.
  • Not having the ability to iterate the fields
  • Not having the ability to look up fields dynamically
  • At odds with TypeScript, a very popular superset of JavaScript
  • At odds with nearly all other languages that do the same thing

@ljharb Giving up all that because its ergonomic is a good reason but if using ## would mean # would never be approved even though ??, ?. and :: are out there now.

A private function introduced into the function, like super could remedy all of these problems. It can have sugar to use the private keyword. It is also more inline with existing syntax. I realize that the TC39 must have approved this thus far, but it isn't too late. Stage 3 it is still not too late, and I hope the TC39 strongly reconsiders these problems.

@bakkot
Copy link
Contributor

bakkot commented Feb 1, 2018

@babakness I am strongly opposed to any proposal which has private x as the declaration and does not have this.x for access for the reasons given in the FAQ.

@babakness
Copy link
Author

babakness commented Feb 1, 2018

@bakkot This is not correct, a private x is only sugar for a function private(this,'parameter') which can be called directly to access other objects (or return undefined if no access).

@babakness
Copy link
Author

We type orders of magnitude more functions out--the ergonomic debate is moot in comparison.

@babakness
Copy link
Author

The private function is class scope only like the super function

@jridgewell
Copy link
Member

jridgewell commented Feb 1, 2018

If that is unergonomic, how does one will to declare or use any functions at all?

It's extremely unergonomic. This is like "why have operator overloading" in every language, because native syntax is better than boilerplate.

  • Altering the consistency of the language this.#foo !== this['#foo']

    • We agree that this is a downside, but we see it as minor.
  • Using up the most convenient symbol left not allowing future use of it.

    • As previously discussed, we're not going to hold back an important feature because something might come along later that's a better fit for #. (side note: I can't think of any.)
  • Not having the ability to iterate the fields
    Not having the ability to look up fields dynamically

    • As previously discussed, we're not convinced this is a use case yet. Privates can only be declared statically (so you already know the keys), making them more akin to records than dynamic objects.
  • At odds with TypeScript, a very popular superset of JavaScript

    • TypeScript's private was a mistake, and it only works because it has a type system to enforce it.
  • At odds with nearly all other languages that do the same thing

    • Because we don't use a private keyword? I think that's severely overstating the position. We are at odds because we're pursuing (strictly, we will not consider anything else) hard private fields, where others went with soft private and regretted it.

To be honest, if it was ## people would probably just let it slide.

I'm not sure how this helps the ugliness argument at all. It's definitely worse when repeated.

@bakkot
Copy link
Contributor

bakkot commented Feb 1, 2018

@babakness

This is not correct

Perhaps I don't understand your proposal. What would this print?

class A {
  private field = 'foobar';
  constructor(){
    this.field = 'baz';
  }
}
const a = new A;
console.log(a.field);

If the answer is 'baz', then my objection above holds (or the field isn't private at all, I guess). If it's undefined, you've either changed the semantics of this or of .field, neither of which seem acceptable. If it throws at a.field, you've broken encapsulation, which is also unacceptable.

I am not particularly concerned with what is sugar for what. I'm concerned with the observable behavior of the code as written.

@babakness
Copy link
Author

babakness commented Feb 1, 2018

@bakkot You'd use private(this,'field') inside the class to get 'foobar'. Outside (a.field) gives 'baz'. Also, private function is not available outside the class. If you receive a reference to a different object you could do private(obj,'field') and it will give you the result if you have access to it.

@bakkot
Copy link
Contributor

bakkot commented Feb 1, 2018

@babakness OK, that was my understanding. In which case my objection stands:

I am strongly opposed to any proposal which has private x as the declaration and does not have this.x for access for the reasons given in the FAQ.

Your proposal has private x for declaration and does not have this.x for access.

@littledan
Copy link
Member

OK, it sounds like we won't be coming to agreement on a change in syntax here. Closing the issue for that reason.

@babakness
Copy link
Author

Forgot to update, I had a good conversation with someone on the TC39 committee. Looking at the Ruby syntax, it is true that it is clear that class / instance attributes are visibly distinguished anywhere they are used. Ruby's approach makes sense--to make something public you have to explicitly set getter / accessors. Sort of like exposing a variable in a closure through a getter.

I feel that the current FAQ doesn't do a good job explaining the depth of the motivations well. That said, I admit that I'm leaning towards the syntax now given all parameters.

@littledan
Copy link
Member

PRs to the FAQ are welcome!

@nevcos
Copy link

nevcos commented Apr 18, 2018

I also do completely dislike the # proposal and it's incredible to see that even "nobody" liking it, the proposal team continues insisting on this.

I do think that the class bring some good things, but was not complete at all:

  1. it doesn't make any sense to not have all methods bind to the class instance;
  2. it would be much readable and less error prone to not need the this. every time
  3. it doesn't have class attributes
  4. it doesn't include private access attributes/methods

Basically the class has much less than we have just using functions/prototypes ... and worse, now we've more problems to solve.

If the class idea was just to get to a syntax that people from other languages know how to use, then why not work in order to make it really understandable and simple to use, like this?

class Animal {
  private static THOUGHTS = "internal thoughts";
  private secret;
  protected eats;
  public color;

  constructor() {
    init();
  }
  private init() {
    secret = THOUGHTS;
  }
}

class Rabbit extends Animal {
  constructor() {
    super.eats = "Carrots";
    // or 
    color = "White";
  }
}

We have already scoped variables today in functions, why not having something similar on class context?

I mean... there could be awesome technical explanations that make one approach harder than other, but please do not make Javascript a Frankenstein with no need... this makes me remember of this:
image

@ljharb
Copy link
Member

ljharb commented Apr 18, 2018

@nevcos it makes perfect sense not to have all methods bind; builtins need to be representable with class, and Array.prototype.slice.call must work - what makes less sense is auto-binding. Separately, class was intentionally incomplete so as to ship something, which is why this proposal and others exist - to flesh it out.

@jkrems
Copy link

jkrems commented Apr 18, 2018

I also do completely dislike the # proposal and it's incredible to see that even "nobody" liking it, the proposal team continues insisting on this.

@nevcos There's plenty of people who like or at least are fine with the currently proposed sigil (I'm one myself and I've talked with a bunch of others). They just have little reason to be active in these issues. :)

@nevcos
Copy link

nevcos commented Apr 18, 2018

@ljharb:

Array.prototype.slice.call must work

And it can continue to work. Assuming that everything is bound to the class instance, means that:

  • Array shouldn't use a class and that's fine, or...
  • The methods are bound to class instance by default, and that is only "overridable" by calling .bind(that) or .call(that) explicitly, or ...
  • There's a new special keyword to specify that the context is "overridable", like functional slice()

@jkrems: I'm sure that if you do a poll you'll have a good answer for that.

@thysultan
Copy link

@nevcos The following is another relevant alternative proposal-private-methods-and-fields.

Not withstanding the unresolved design issues present with the current #sigil, additionally it might be of fruit to document and collect all the relevant push back/issues with/against the use of a sigil within the JavaScript community in addition to the poll you propose in order to collect the relevant data that could hopefully be presented at the next TC39 meeting and other relevant mediums.

@nevcos
Copy link

nevcos commented May 4, 2018

Just thinking again on this problem, we have already a way of having "real" private members by using Symbols:

const DIGIT = Symbol("DIGIT");
export class Request {
    get digit() {
        return this[DIGIT];
    }

    set digit(digit) {
        this[DIGIT] = digit
    }
}

The only drawback that I see is that the members are not available on the subclasses.

Thanks

@ljharb
Copy link
Member

ljharb commented May 4, 2018

@nevcos Symbols are in no way private, and are in fact always fully public. Object.assign copies enumerable Symbols, and Object.getOwnPropertySymbols/Object.getOwnPropertyDescriptors/Reflect.ownKeys etc all expose symbol keys.

@nevcos
Copy link

nevcos commented May 4, 2018

@ljharb Ok, good to know 👍, thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants