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 name
private #foo;
function f() { return { with #foo: 1 }; }
f().#foo
function 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