Private field and method declarations do two things at once: they position the scope/availability of the private element, and they define its meaning. This proposal allows those two functions to be separated: private declares the scope, and with defines it in a class or object.
private #foo;
class C { with #foo; } // reference the outer definition
new C().#foo; // works, since we're within the scope of the nameprivate #foo;
function f() { return { with #foo: 1 }; }
f().#foofunction counter() {
return {
#counter: 1, // defined within this object only
inc() { return this.#counter++; }
}
}Rules: There must be exactly one with per private, and this must be in the same unit of parsed code (i.e., the restriction is enforced by static semantics). It is not possible to use with on a name which was not explicitly defined by private. private definitions may be shadowed by other private definitions, or by keywordless definitions.
Invariants met:
- No real new stuff: this just splits up the scoping and definition into two places.
- This "excavates"/"explains" the existing construct as
class C { private with #x }(though that syntax would be invalid)
- This "excavates"/"explains" the existing construct as
- Scoping for classes and objects is the same; no lack of parallelism
- Private names are still only defined once, so they still stand for just a single "brand"
- Implies that brand-checking is a valid implementation of private methods
- Implies that private names still provide a good basis for "nominal types"/Wasm RTT equivalence