-
Notifications
You must be signed in to change notification settings - Fork 113
Evaluate using ::
instead of #
as "sigil"
#216
Comments
I don't adore the You made a good point though, we could definitely consider using 2 characters and as far as these go, The one downside I immediately thought of when I came across this is that I wanted the This-Binding operator proposal to go through, and it was set on using Apparently that other proposal may not really be going anywhere anytime soon, though; and the Smart Pipelines, which I am particularly fond of, would:
As a side note, apparently that other proposal did receive some pushback on the grounds that:
All in all, it seems to me like "stealing" the |
Strongly prefer keeping
All due respect, I have to strongly disagree with that characterization. Namespacing is very different from private fields/methods. Three off-the-cuff reasons not to use 1. Since 2. Smart Pipelines only subsume one of the three uses of
(their emphasis) Using it for private instead effectively closes off the bind operator proposal (which still could progress in some form), since using something else for it given the prior art in Java seems unlikely. 3. I recommend moving forward with |
class A {
static staticProperty = 'static Property';
static name = 'i can declare any name for static property/method';
static apply() {
/**
* current implementation for static properties
* and methods (TS, Babel) are broken
* coz it will be compilled into something like this:
* const A = (constructor => {
* constructor.staticProperty = 'static Property';
* THROW ERROR, name property has not setter!
* constructor.name = 'i can declare any name for static property/method';
* seriously? =/
* constructor.apply = function apply() { ... };
* return constructor;
* })(class A {})
*
* it will be better to use # for static properties
*
* A#staticProperty
* A#name
* A#apply
*
* static properties cannot dynamic accessed
* A#['invalid syntax']
*
* static properties constant
*
* A#staticProperty = 'must throw error';
*
* coz it is same as:
* import * as all from 'module';
* all.importedVariable = 'new value';
*
* // dot access to usual properties
* A.name === 'A';
*/
}
//=>private = 'incorrect syntax, private methods/properties allowed only with this keyword
//->protected = 'incorrect syntax, protected methods/propertirs allowed only with this or super keyword
constructor(init) {
this.public = init;
// fat arrow for private access
this=>a = 'private variable A';
this=>method = () => {
// use arrow function for creating private method
// this context never changed
console.log(this);
}
// thik arrow for protected access
// same name allowed
this->a = 'protected variable A';
this->method = () => {
// use arrow function for creating protected method
// this context never changed
console.log(this);
}
}
set privateA(value) {
this=>a = value;
}
get privateA() {
return this=>a;
}
set protectedA(value) {
this->a = value;
}
get protectedA() {
return this->a;
}
}
class B extends A {
static staticProperty = 'new value for static property, other properties should be extended';
/**
* console.log(B#staticProperty === 'new value for static property, other properties should be extended'); // true
*
* console.log(B#staticProperty === A#staticProperty); // false
* console.log(B#name === A#name); // true
*/
constructor(init) {
super(init);
this.public = 'new value';
this=>a = 'private variable B';
console.log(this.privateA) // 'private variable A'
this.privateA = 'set the next value';
console.log(this.privateA) // 'set a next value'
// this=>method();
// throws undefined is not a function, coz of this=>method not defined in this context
console.log(this.protectedA) // 'protected variable A';
this->a = 'set the next value';
console.log(this.protectedA) // 'set the next value';
this->method() // B { public: 'new value' }
this->method = (value) => {
// use super keyword for base class protected properties an methods
super->a = value
super->method();
}
this->method('set another value to protected a') // B { public: 'new value' }
console.log(this.protectedA); // 'set another value to protected a'
}
}
class C extends A {
constructor(init) {
super(init);
this=>a = 'ok, lets another try';
console.log(this.privateA) // 'ok, lets another try'
this.privateA = 'and another try';
console.log(this.privateA) // 'ok, lets another try'; coz of privateA setter used from A;
}
get privateA() {
return this=>a;
}
}
const a = new A('new A');
a['=>a'] = 'try to access private property';
console.log(a); // A { public: 'new A', '=>a': 'try to access private property'}
const tryToGetPrivateProperty = a=>a // is a function coz it is valid arrow function syntax
// console.log(a->a);
// syntax error, thik arrow syntax allowed only with this an super keyword |
If you're saying that being able to (re)define "use strict";
class Example { }
console.log(Object.getOwnPropertyDescriptor(Example, "name"));
Object.defineProperty(Example, "name", {
value: "foo"
});
console.log(Example.name); // "foo"
"Static" fields being properties of the constructor function is very well established in existing code, there's no need to come up with new syntax for it. |
Having said that, I could see an argument for disallowing using the new syntax to create a |
@nicolo-ribaudo I think he/she is using a slightly outdated version of the plugin. As you can see in the posted code, it's using assignment to create the |
The rationale is summed up well in #216 (comment) . Thanks for the discussion. |
VERY IMPORTANT NOTE: Anyone who would like to comment here should first read the PRIVATE SYNTAX FAQ. This will save everyone time. Thank you.
The available space of ASCII symbols was exhaustively searched for possible sigil characters. Only the two characters
@
and#
were free. However@
had already been used extensively in the community (Babel, TypeScript) to denote decorators like in Java, Python and other languages.While technically an obvious choice given the constraints, the visual appearance of
#
has resulted in unnecessary initial objections by JS developers for the looks alone (see issues here, on reddit, the implementor's issue trackers, …). While technical considerations should have priority, both elegance as well as developer mind share do count.By allowing two character instead of just one, the space of symbols can be widened. This way the double colon
::
becomes available. In Rust, C++ and others,::
is used for namespacing, which is a different but related concept, making mental associations easy. At the same time::
has a cleaner look, that's also more aligned to the overall visual identity of JavaScript:Therefore it could be wise to re-evaluate using
::
as a sigil to denote private varialbes and their access, keeping everything else the same.The text was updated successfully, but these errors were encountered: