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

Why not use obj#prop instead obj.#prop ? #39

Closed
uMaxmaxmaximus opened this issue Jul 31, 2016 · 9 comments
Closed

Why not use obj#prop instead obj.#prop ? #39

uMaxmaxmaximus opened this issue Jul 31, 2016 · 9 comments

Comments

@uMaxmaxmaximus
Copy link

uMaxmaxmaximus commented Jul 31, 2016

Dot accessor will mean public prop obj.prop
Sharp accessor will mean private prop obj#prop

Example:

class Cat {

  constructor(name){
    this#name = name
  }

  #say() {
    alert(`My name ${this#name}`)
  }

}

var q = new Cat('Tom')
q.say() // error
q#say() // error

Example 2:

class Point {

  set x(value){
    this#x = value 
  }

  get x(){
    return this#x 
  }

}

Example 3:

class Collection {

  self(){
    return this
  }

  #say(){
    alert('i am private')   
  }

  run(){
    this.self()#say() // alert("i am private")
  }

}
@uMaxmaxmaximus uMaxmaxmaximus changed the title Why not use obj#prop within obj.#prop ? Why not use obj#prop instead obj.#prop ? Jul 31, 2016
@littledan
Copy link
Member

littledan commented Aug 3, 2016

I don't see a big advantage here. The motivation for obj.#prop rather than obj#prop is that it will avoid an ASI hazard that would otherwise come from the #foo shorthand. That is, the following would be ambiguous:

class X {
  #y
  z() {
    w()
    #y()
  }
}

Should that parse as w()#y() or w(); this#y()? You could imagine programmers expecting the latter.

@uMaxmaxmaximus
Copy link
Author

uMaxmaxmaximus commented Aug 4, 2016

you can not simply write sharp and property
sharp is accessor like a dot
You can write only like this:

class X {

  z() {
    w()
    this#y()
  }

  #y(){  }
}

There is no ambiguity. Do not use their antiquated concepts to my decisions. I proposed a completely new semantics. It is clear that my decision suggests that the MY semantics rather than your obsolete.

Here is the link to the description of my semantics #36

People dislike expansions that my decision is simply not able to recognize my genius and the genius of my decision. I feel that I need to write their own language and its compiler so that the world saw that I was right and was always right.

I have already begun experiments https://www.npmjs.com/package/es-privates-loader

@uMaxmaxmaximus
Copy link
Author

or just double dot

class Cat {
  constructor(){
    this..privateArr = []
  }

  ..privateFunc(){
    this..privateArr.push()
  }
}

@ckknight
Copy link

0..toString() is valid syntax today, so using .. for private access might create extra ambiguities.

@eggers
Copy link

eggers commented Sep 14, 2016

What about this#.? It kind of says "this' privates' dot"

@littledan
Copy link
Member

I prefer the .# syntax. Starting with a . evokes property access, and the # makes it the same in its definition and usage. As discussed above, foo#bar will not work due to the ASI hazard. Let's stick with the current proposed syntax.

@jamiter
Copy link

jamiter commented Jun 7, 2017

@littledan, is their any documentation on why the shorthand even exists? I'm not sure yet why private properties get a shorthand while public properties do not have a shorthand. Typing this#foo instead of #foo is a lot more clear in my opinion.

@littledan
Copy link
Member

cc @wycats @dherman who are the staunchest champions of the shorthand.

Even if the shorthand didn't exist, I kinda like the obj.#x syntax--it reinforces that #x is just a name that starts with #--it's the # at the beginning of a name that makes it private. To call fields or methods, you use . followed by a name. This way, you can think of things sort of like, at a high level, we are not introducing a new operator, just a new kind of name.

@wycats
Copy link
Contributor

wycats commented Jul 13, 2017

I just wanted to write down my basic thoughts in favor of the shorthand, especially since a number of people have raised questions recently.

Firstly, I agree that the mental model of private state is extremely important, and wouldn't want to sacrifice clarity for "typing less". However, I believe that the shorthand syntax suggests a reasonable mental model, and also that the .# syntax raises mental model questions of its own.

The Mental Model of the Shorthand Syntax

  • Fields, methods without the # ("public") are part of an object's public interface. From the perspective of the class, they are "the way code interacts with me from the outside". Code uses this.XXX to use the class' "outside" interface.
  • Fields and methods with # ("private") are the object's internal interface. From the perspective of the class, they are "the way I interact with myself". Code uses #XXX to use the class' "inside" interface.

Notably, it is possible for a class to want to use its own public interface on purpose (for example, when calling methods or accessors that are intended to be overridable). For a class' own code, the distinction between "the outside interface" and "the inside interface" is important.

People have argued that private state should have symmetry with this.XXX, and I agree that there is some benefit to leaning on existing intuitions about the meaning of this. However, I also think that those intuitions include the "externally accessible" aspect of the syntax.


Some have argued that the only way to plausibly understand #foo (and especially #foo()is as an expansion intothis.#fooandthis.#foo()`. My view is that the new syntax (and especially its very obvious "newness") will give people an expectation that there's something to learn.

Fundamentally, my opinion boils down to this: I think that "#foo() is the way you call methods on yourself" is a very plausible intuition that will feel natural.


People have also raised problems like this to illustrate that #foo introduces new footguns:

class {
  #name;

  setup() {
    document.body.onclick = function() { #print(); }
  }

  #print() {
    console.log(#name);    
  }
}

The argument is that it's not obvious, without the this, that there's something strange about the inner function. I think this argument boils down to the idea that the way we should teach the strangeness of nested functions is by appealing to this.

There's an alternative way to teach it, which is to say that "the inner function is no longer running in the same object". This is, in fact, somewhat important, because other constructs that aren't inherited into nested functions also don't contain this.

In general, the way to avoid this kind of footgun is to use arrows, and a way to understand nested functions is "doesn't inherit anything that has to do with the current instance".

Bottom line: I think that, especially with these new features, we will need a way of teaching classes that is natively about classes, and that the kinds of problems people are worried about here are really about the limits of stretching the ES5 mental model to an increasingly sophisticated class model.

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

6 participants