Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add protected #x #6

Open
Igmat opened this issue Apr 6, 2019 · 5 comments
Open

Add protected #x #6

Igmat opened this issue Apr 6, 2019 · 5 comments

Comments

@Igmat
Copy link

Igmat commented Apr 6, 2019

What about adding protected #x notation? It seems to be natural extensions to this proposal, since majority of developers will expect to have public/private/protected keywords used in same fashion and might be surprised if something is missing (it also appliable to #5).

protected keyword might solve positional vs closure problem described in tc39/proposal-class-fields#60

Let's make protected the same as private whith one exception, private belongs to closure scope, while protected belongs to lexical scope. To illustrate:
private

function mixin(klass) {
  private #x;
  return class extends klass {
    #x = 1;
    add(obj) {
      return this.#x + obj.#x;
    }
  }
}
const A = mixin(class {});
const B = mixin(class {});
const a = new A;
const b = new B;
a.add(a); // works
a.add(b); // throws, since their `#x` are different, because created per closure scope

protected

function mixin(klass) {
  protected #x;
  return class extends klass {
    #x = 1;
    add(obj) {
      return this.#x + obj.#x;
    }
  }
}
const A = mixin(class {});
const B = mixin(class {});
const a = new A;
const b = new B;
a.add(a); // works
a.add(b); // works, since their `#x` are the same, because created per lexical scope

protected could be extremely useful for some types of mixins, while others are still possible.
BTW, @ljhard, this type of protected actually does protect something 😉

It works even better with #1. For example:

function mixin(klass) {
  return class extends klass {
    protected #x = 1;
    add(obj) {
      return this.#x + obj.#x;
    }
  }
}

Addition

It might be extended a little bit in root-level lexical scope. Consider this:

export class A {
  protected #x;
}

Without any specific behavior protected at root-level lexical scope will behave exactly the same as private, so previous code will be euqal to following:

export class A {
  private #x;
}

But to make it closer to meaning of protected from other languages, we may change this a little bit, so code will be equal to:

export private #x;
export class A {
  #x;
}

P.S.

I'm not sure what term will be preferable for this proposal: lexical scope or outer closure scope. They probably might have slight difference, but I don't see how it can affect this proposal.

@ljharb
Copy link
Member

ljharb commented Apr 6, 2019

I firmly believe that "protected" has no place in JavaScript; primarily because there's no way to reliably "protect" anything. Access isn't a "level", it's a binary - either something is reachable, or it's not. If it's reachable, it's public, and if not, it's private.

@Igmat
Copy link
Author

Igmat commented Apr 6, 2019

@ljharb, please re-read my post. protected is FULLY private and isn't reachable in any sense.
The only difference is scope to which it belongs (but this scope is still FULLY controlled by author).

Do you understand my idea and why I say that protected it isn't reachable?

@ljharb
Copy link
Member

ljharb commented Apr 6, 2019

so you're suggesting to use protected as a kind of outer, a keyword that hoists the declaration to a higher scope?

@jridgewell
Copy link
Member

I think he's suggesting protected is the same as private, except it per source location and not per evaluation. Ie, tc39/proposal-class-fields#60

I think that's a bit confusing. Why not just hoist the private declaration one scope higher?

@Igmat
Copy link
Author

Igmat commented Apr 8, 2019

Why not just hoist the private declaration one scope higher?

It's not always suitable, consider this:

const mixinA = klass => {
  protected #id;
  return class A extends klass {
    [#id] = 1;
  }
}
const mixinB = klass => {
  protected #id;
  return class B extends klass {
    [#id] = 1;
  }
}

Moving protected #id to higher scope as private #id will cause name conflict.

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

No branches or pull requests

3 participants