Arrow methods
The missing colon ":" is intentional.
Not sure what the benefit here is:
- You can do
foo: () => bar
for objects - You can do
foo = () => bar
for class instances using the public fields
proposal.
This leaves out self-binding, but you could always use a local variable if necessary. (It's like one extra line, maybe 3, and it's not common at all.)
Consistency and sugar. Changing from arrow and non-arrow method is a diff
between =>
where:
foo() {} mirrors foo: function () {} foo() => {} mirrors foo: () => {}
Also the "this" reference in the second variant is not the class instance i.e it is part of the shared prototype.
It has an added reach in usefulness when you consider nested classes:
class A { foo() { return class B { bar() => { return this // refers to instance A } } } }
This is not possible today without creating a self-like variable for bar to reference A's instance; Which is one of the points arrow functions addressed.
On Fri, Nov 16, 2018 at 12:42 PM Sultan <thysultan at gmail.com> wrote:
Consistency and sugar. Changing from arrow and non-arrow method is a diff between
=>
where:foo() {} mirrors foo: function () {} foo() => {} mirrors foo: () => {}
Yes, but note that the first one actually contains sugar - it lets you omit a decent chunk of characters (at bare minimum, nine) and puts the name next to the arg-list again, like how normal functions look.
The second lets you omit exactly one character. It also makes it look more like a named function declaration, while arrow functions are always name-less, so it's not helping you return to a "normal" form either.
Also the "this" reference in the second variant is not the class instance i.e it is part of the shared prototype.
It has an added reach in usefulness when you consider nested classes:
class A { foo() { return class B { bar() => { return this // refers to instance A } } } }
This is not possible today without creating a self-like variable for bar to reference A's instance; Which is one of the points arrow functions addressed.
Instance methods that don't refer to the instance are definitely the
exception, not the rule. Reading this code, I would absolutely
expect on first and probably second glances for this
to be referring
to the B instance, not the A instance. Binding A's this
to a
different name is actually a readability aid in this circumstance,
unlike the many cases that arrow functions were designed to replace.
This looks to me like a decent argument against the suggestion. :/
On Fri, Nov 16, 2018 at 9:52 PM Tab Atkins Jr. <jackalmage at gmail.com> wrote:
...while arrow functions are always name-less...
Minor nit-pick: Arrow functions are often named:
const foo = () => {
console.log(foo.name);
throw new Error();
};
foo();
Fiddle: jsfiddle.net/1gpbvx06
Running that, you'll see something like this in the console:
foo
Uncaught Error
at foo ((index):35)
at (index):3
(Edge doesn't show the stack trace in the console, but if you step into
foo
, it shows the proper name in the call stack.)
Search for SetFunctionName in the spec to find all the various places anonymous function expressions (both traditional and arrow) assign names to functions as of ES2015. (Basically: Anywhere the expression result is assigned to a variable, constant, or default parameter value; or when it's assigned to a property in an object initializer [but not when assigned to a property on an existing object].)
</nit-pick> ;-)
-- T.J. Crowder
On Fri, Nov 16, 2018 at 8:42 PM Sultan <thysultan at gmail.com> wrote:
It has an added reach in usefulness when you consider nested classes:
class A { foo() { return class B { bar() => { return this // refers to instance A } } } }
This is not possible today without creating a self-like variable for bar to reference A's instance; Which is one of the points arrow functions addressed.
It is, just not within the class
construct:
class A {
foo() {
class B {
}
B.prototype.bar = () => {
return this; // refers to instance A
};
return B;
}
}
I agree with Tab Atkins Jr.: In your nested classes example, I'd expect
this
within bar
to be the B
instance, not the A
instance. I think
the more natural definition of that syntax (if it were adopted) would be a
prototype function that is effectively auto-bound to the instance at
construction time, like this common pattern today:
class B {
constructor() {
this.bar = this.bar.bind(this);
}
bar() {
return this;
}
}
In fact I could see some benefit to that syntax, since people use class fields for that use-case which can make mocking difficult.
But I'm not keen on that syntax with the semantics you're proposing.
-- T.J. Crowder
C# has a similar syntax for shorthand expression bodies (dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#expression-bodies-on-method-like-members):
class Point {
private int x;
private int y;
…
// expression bodied getters (read-only)
public int X => x;
public int Y => y;
// expression bodied method
public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
}
From: es-discuss <es-discuss-bounces at mozilla.org> On Behalf Of T.J. Crowder
Sent: Sunday, November 18, 2018 6:31 AM To: Sultan <thysultan at gmail.com>
Cc: es-discuss at mozilla.org Subject: Re: Arrow methods
On Fri, Nov 16, 2018 at 8:42 PM Sultan <thysultan at gmail.com<mailto:thysultan at gmail.com>> wrote:
It has an added reach in usefulness when you consider nested classes:
class A { foo() { return class B { bar() => { return this // refers to instance A } } } }
This is not possible today without creating a self-like variable for bar to reference A's instance; Which is one of the points arrow functions addressed.
It is, just not within the class
construct:
class A {
foo() {
class B {
}
B.prototype.bar = () => {
return this; // refers to instance A
};
return B;
}
}
I agree with Tab Atkins Jr.: In your nested classes example, I'd expect this
within bar
to be the B
instance, not the A
instance. I think the more natural definition of that syntax (if it were adopted) would be a prototype function that is effectively auto-bound to the instance at construction time, like this common pattern today:
class B {
constructor() {
this.bar = this.bar.bind(this);
}
bar() {
return this;
}
}
In fact I could see some benefit to that syntax, since people use class fields for that use-case which can make mocking difficult.
But I'm not keen on that syntax with the semantics you're proposing.
-- T.J. Crowder
As the name suggests; An update to the grammar related to methods on objects/classes to support arrow methods:
today: {render() { return 'Hello' }} proposed addition: {render() => 'Hello'}
This could be some-what linked to class fields in the class variant; That is what does "this" refer to when used in a class.