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

and yet another suggestion for "private but not closure" #153

Closed
yw662 opened this issue Oct 19, 2018 · 16 comments
Closed

and yet another suggestion for "private but not closure" #153

yw662 opened this issue Oct 19, 2018 · 16 comments

Comments

@yw662
Copy link

yw662 commented Oct 19, 2018

roughly just replace # with .private., which make much more sense.

since you dont like it, just try Symbol.private

example:

class foo {
    [Symbol.private] = {
        // need magic here to make it truly private
        x: 0
    }
    function bar() {
        this[Symbol.private].x += 1; // approved
    }
    ...
}
...
(new foo())[Symbol.private].x // denied

This will introduce a new well known Symbol Symbol.private, and the only thing the engine need to do is, make object[Symbol.private] private.

@ljharb
Copy link
Member

ljharb commented Oct 19, 2018

That would conflict with a public "private" property, which works just fine in existing JS.

@yw662
Copy link
Author

yw662 commented Oct 19, 2018

@ljharb
But different from #, no one will name a member "private" if the one do not want it private.

@ljharb
Copy link
Member

ljharb commented Oct 19, 2018

Absolutely they would. Any existing possible public property can't be repurposed.

@yw662
Copy link
Author

yw662 commented Oct 19, 2018

However, private is reserved. No one "should" use it actually. And "private" never serve as a good name. Lets say, no one "actually" do it.

@ljharb
Copy link
Member

ljharb commented Oct 19, 2018

It's a reserved keyword - not a reserved property name. Anyone can do it, and "should" is irrelevant.

@littledan
Copy link
Member

Agree with @ljharb: there is likely to be significant web compatibility impact if we choose a name like this that's legal, and for many years, even keywords have been permitted as property names.

@aimingoo
Copy link

aimingoo commented Oct 19, 2018

@yw662 "private but not closure" implementation in #154 , source code released at example.js in aimingoo/private-property.

@yw662
Copy link
Author

yw662 commented Oct 19, 2018

object.private might shadow legal property names, but it shadow only 1 property name.

However, # stuffs are also legal property names, and you will shadow all of them.

If you really worry about this, we can do object[Symbol.private].

@nicolo-ribaudo
Copy link
Member

No, because you can't use # to access a public property:

var obj = {
  "#foo": 2
};

obj.#foo; // This code is currently not valid! You will always need to `obj["#foo"], which never access private properties

@yw662
Copy link
Author

yw662 commented Oct 19, 2018

not a problem.
foo.bar and foo['bar'] should always have the same meaning if both are valid.

@nicolo-ribaudo
Copy link
Member

nicolo-ribaudo commented Oct 19, 2018

foo.bar is valid (and thus the same as foo["bar"]) only for identifier-like property names. #bar is not identifier-like.

Also, your proposal isn't much more ergonomic that the current way of having private properties, while the current proposal is:

// ES6

var x = new WeakMap;
class Foo {
  constructor() {
    x.set(this, 0);
  }

  setX() {
    x.set(this, 1);
  }
}

// Your proposal

class Foo {
  [Symbol.private] = {
    x: 0,
  };

  setX() {
    this[Symbol.private].x = 1;
  }
}

// Current proposal

class Foo {
  #x = 0;

  setX() {
    this.#x = 1;
  }
}

Also, what is this inside private methods? If it is the "privates" object, how can I access the class? If it is the class, then this[Symbol.private].foo() isn't the same as this[Symbol.private].foo.call(this[Symbol.private]), which is one of the building blocks of how foo.bar() works.

@yw662
Copy link
Author

yw662 commented Oct 19, 2018

should be this[Symbol.private]
2 way to solve that problem:
set prototype of this[Symbol.private] to this
or
introduce another Symbol.public

@nicolo-ribaudo
Copy link
Member

should be this[Symbol.private]

I don't think that anyone would accept a private props implementation where this inside a private function isn't the instance.

set prototype of this[Symbol.private] to this

I don't think that this would work:

  1. if it needs to be manually set by the developer, we are using the wrong behavior by default
  2. it can't be manually done by the engine:
    var obj = {
      foo() { return this.x; },
      __proto__: { x : 1 }
    };
    obj.foo(); // works
    
    class A {
      [Symbol.private] = obj; // Modifies obj.__proto__
    }
    
    obj.foo(); // Doesn't work :(

introduce another Symbol.public

How would that work?

@whtiehack
Copy link

I can't imagine how to think of using # as a private variable tag.

@lanistor
Copy link

No # Union, join us.

@littledan
Copy link
Member

It's really not clear how Symbol.private could provide the encapsulation goals in this proposal, so closing this issue.

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

7 participants