Field initializers
Interesting concept... What about inheritance?
Inherited methods would inherit the same behavior, since this is just syntactic sugar after all.
class Point {
setPosition(this.x, this.y) {}
// same as
// setPosition(x, y) { this.x = x; this.y = y }
}
class Rectangle extends Point {
setSize(this.width, this.height) {}
// same as
// setSize(width, height) { this.width = width; this.height = height }
}
let rect = new Rectangle()
rect.setPosition(0, 0)
rect.setSize(50, 50)
rect // { x: 0, y: 0, width: 50, height: 50 }
I'd think with the advent of private fields a much more common (and better) use case would not involve creating publicly visible properties - how might that work?
Perhaps this:
class Foo {
constructor(#x, #y) { }
}
I usually just use Classes and constructor functions for simple data structures. Only allowing this for private fields seems counter-intuitive to that. Why not both?
How about own
keyword? It might work with public and private fields, and
seems more elegant (because of destructuring we have a lot of symbols in
the paremeters declaration)
// This will throw a SyntaxError?
class Rectangle {
constructor(own #x, own #y, own name) {}
}
There's a new proposal using the own
keyword in class fields declaration (
erights/Orthogonal-Classes). It might fit perfectly.
On Sat, Mar 18, 2017 at 6:04 PM, Jordan Harband <ljharb at gmail.com> wrote:
I'd think with the advent of private fields a much more common (and better) use case would not involve creating publicly visible properties - how might that work?
Perhaps this:
class Foo { constructor(#x, #y) { } }
It seems strange to me to advertise your private properties like that, but of course, the source is right there anyway...
Worth noting the TypeScript prior art:
// (TypeScript)
class Example {
constructor(public x, public y) {
}
}
const e = new Example(1, 2);
console.log(e.x); // 1
console.log(e.y); // 2
Note the access modifier on the parameters. (private
works as well.)
So quite similar to Jordan's constructor(#x, #y)
for private data (if
that horrible #
does in fact happen in the private data proposal), and to
"just nobody"'s constructor(this.x, this.y)
for instance properties.
I don't see any point to having this on methods. On constructors, I suppose it's a bit of convenience.
More prior art, this time from C#, which shifts the burden from the constructor to the call to it: You can set accessible properties in an initializer after the call to the constructor:
var obj = new Example() { x = 1, y = 2};
Console.WriteLine(obj.x); // 1
Console.WriteLine(obj.y); // 2
-- T.J. Crowder
I don't see any point to having this on methods. On constructors, I suppose it's a bit of convenience.
If it's supported on constructor functions, my reasoning was that it'd only make sense for it to be supported on methods (which are also just functions). Having this syntax available for functions allows really nice, convenient data structures, and getter/setters as I've displayed in my original post.
function UserData(
this.name,
this.age,
this.gender,
) {}
// probably more readable / better practice in usage, works just as well:
function UserData({
name: this.name,
age: this.age,
gender: this.gender,
}) {}
While I'm on that subject, thoughts on this being equivalent to the above?
function UserData({
this.name,
this.age,
this.gender,
}) {}
I don't really like it because it looks very similar to the approach with named arguments; the braces are easy to miss, but it's still very succinct.
How about
own
keyword? It might work with public and private fields, and seems more elegant (because of destructuring we have a lot of symbols in the paremeters declaration)
I'm against piling on too many unfamiliar language constructs. Even without
knowing ES2015+, the semantics of this.*
assigns in a function
declaration are easily understood at a first glance, and meshes nicely with
everything else available in the language as is.
More prior art, this time from C#, which shifts the burden from the constructor to the call to it: You can set accessible properties in an initializer after the call to the constructor:
Not for this either. This is easily done with Object.assign
and similar.
const obj = Object.assign(new Example(), { x: 1, y: 2 })
I'm not saying we couldn't do both; I"m saying we wouldn't want to make "public" easy unless "private" was equally easy, because private is a better default.
Would it be possible to have syntax like this? It's a feature supported by other JS variants in some way (CoffeeScript, TS) that feels missing from the spec. It's mainly useful as a convenient, terse way of setting properties of an object directly from its arguments.
class Rectangle { constructor (this.x, this.y, this.width, this.height) {} setPosition(this.x, this.y) {} setSize(this.width, this.height) {} } // equivalent to class Rectangle { constructor (x, y, width, height) { this.x = x this.y = y this.width = width this.height = height } // ... } // for regular functions as well function Rectangle (this.x, this.y, this.width, this.height) {}
Deconstruction and argument defaults should all work similarly.
function Point([this.x, this.y]) {} function Point({ x: this.x, y: this.y }) {} function Point(this.x = 0, this.y = 0) {}