Shorter syntax for arrow function assignment

# Brian Blakely (6 years ago)

A prevalent pattern has emerged:

export const foo = ()=> { };

Taking a cue from short method syntax, this comes to mind as a possible improvement:

export const foo() { };

Even better if we assume const:

export foo() { };

That is delicious. Thoughts?

# kai zhu (6 years ago)

-1 this fails styleguide sanity-check.

we currently have 3 common styles of declaring functions:

  1. foo = function () {...}
  2. function foo () {...}
  3. foo = () => {...}

does this extra 4th style offer anything new to justify making the javascript language even less consistent than it already is? i say no.

# Brian Blakely (6 years ago)

This syntax is shorter, easier to write, and arguably easier to read. What else does it need to offer?

# /#!/JoePea (6 years ago)

It can be confusing because it is too similar to non-arrow functions. The arrow syntax is clear in meaning.

# Peter Jaszkowiak (6 years ago)

It needs to offer more than two characters, and no confusing confliction with shorthand method syntax.

# Brian Blakely (6 years ago)

As arrow function const assignments become the norm and non-arrows the exception, allowing syntactical cruft to fall away makes sense to me. It might be premature based on overall 2015 adoption, but I don't see this trend reversing.

# Andrea Giammarchi (6 years ago)

to me this export foo() {} makes sense only as shortcut for export function foo() {} and not as arrow, because arrow missing context and arguments will mislead everyone exporting a named function.

# Michał Wadas (6 years ago)

+1 for omitting function keyword between export and function name.

Declaring arrow functions without arrow in syntax - nope, nope, nope.

# Brian Blakely (6 years ago)

I certainly understand the "misleading" perspective, but also consider ES5- function syntax to be deteriorating such that this shorthand would be wasted on it.

# T.J. Crowder (6 years ago)

Agree with Andrea on this one. Method syntax (in an object initializer, in a class) creates a method (a non-arrow function with a [[HomeObject]] slot), not an arrow function. This looks just like method syntax. The absence of the arrow is too misleading.

I could see it as a shortcut for export function foo() { }, but not for export const foo = () => { };.

-- T.J. Crowder

# Brian Blakely (6 years ago)

ICYMI: my stance is that ES5- functions are already outmoded - and are rapidly becoming the lesser-used option - so it would be a waste of a syntax win.

# dante federici (6 years ago)

My major concern is this can be confusing with the "this" binding. The object wrapping being the only difference between:

// Existing:
const x = {
  myFn() { }
};

// Proposed, with different meaning:
const myFn() { } // Why would "this" bind to myFn?

Omitting the arrow is a major -1 for me -- the whole point of "=>" is that

it does not provide a "this" to the scope of the function body.

Also, you cannot implicitly omit the "const", as these are all valid:

export var symbol = ...
export let symbol = ...
export const symbol = ...
# Brian Blakely (6 years ago)

Also, you cannot implicitly omit the "const"

Paving a cowpath, const has won named function assignment.

# dante federici (6 years ago)

Another annoying thing JS has to deal with is:

// implicitly 'var'
someVar = 10;

So, something like:

myFn() {
}

Would be considered as:

var myFn = function() {
}

with what semantics exist now. Not best practices, but what is currently interpreted in the language.

I'd 100% agree that, as a shorthand, this is nice:

myFn() { }
const myFn = () => {}

Which is what I mean. But I'm not the full implementation of JavaScript.

# Brian Blakely (6 years ago)

At current, sans an explicit assignment, the pragma foo() {...} should throw.

# Andrea Giammarchi (6 years ago)

functions are already outmoded

I don't know where you come from but to me:

// this ain't outmoded at all
const obj = {
  method() { return this === obj; }
};

// this ain't outmoded at all
class Any {
  method() { return this instanceof Any; }
}

And a module that provides mixins is definitively not outmoded at all

export method() {
  return this !== undefined;
};

Omitting the arrow is everything but a syntax win here.

# Matthew Robb (6 years ago)

There is practically no gain to suggest this syntax for arrows anyway as a module has no this binding you are creating a perpetually contextless function whereas using this shorthand syntax for a normal function makes some sense. You lose implicit return regardless.

  • Matthew Robb
# Jordan Harband (6 years ago)

"ES5 functions" - by which you mean, normal functions - are not "outmoded", they remain necessary for any use case where this needs to be determined at invocation time.

Nothing should ever produce an arrow function without =>; and exports

assuming const is an interesting idea, but explicit > implicit, and "typing less" is simply not a goal worth optimizing for by itself.

# Brian Blakely (6 years ago)

normal functions ... remain necessary for any use case where this needs

to be determined at invocation time.

On its way to being an edge case.

# Brian Blakely (6 years ago)

This is the case that is fading away (and probably isn't coming back into vogue ever again):

const Foo = function() {
  this.bar = `b4r`;
};
# dante federici (6 years ago)

The use case fading away doesn't mean you can drop support for it, or that it won't still be in use.

Please stop trying to push your "shorthand" syntax of:

myFn() {
}

It's already been pointed out in multiple cases that:

  1. The current usages are not "outmoded"
  2. The proposed syntax has misleading this binding without the arrow
  3. Blocks, ASI, and the object shorthand notation either conflict or make it vague how to interpret

This isn't a beneficial syntax moving forward, and it doesn't seem to add anything other than "I don't like typing '='".

# Brian Blakely (6 years ago)

To be clear, this isn't a proposal to drop support for something. Don't optimize for a fading use-case, however.

it doesn't seem to add anything other than "I don't like typing '='".

That is absolutely correct, it is a proposal for shorthand syntax.

# /#!/JoePea (6 years ago)

It doesn't matter if functions are being used less, they simply aren't going away. There's plenty of people specifically relying on function for certain purposes where arrow functions do not work. Lets avoid getting arrows confused with functions.

const prototype = /* ... get this prototype object from somewhere ... */

prototype.foo = function foo() {
  // do something with `this`.
}

That sort of stuff (relying on non-arrows) isn't going away. /#!/JoePea

# doodad-js Admin (6 years ago)

On its way to being an edge case.

Not really because arrow functions are not re-bindable. They are always bound to a single object since their creation. They are meant to be used as “lambda” functions”, while providing a workaround for accessing properties of their “parent object” (ie the object referred by “this” at their creation). They are not simply a shortcut version of “function” like many people thinks.

From: Brian Blakely [mailto:anewpage.media at gmail.com] Sent: Tuesday, October 24, 2017 3:39 PM To: Jordan Harband <ljharb at gmail.com>

Cc: dante federici <c.dante.federici at gmail.com>; es-discuss <es-discuss at mozilla.org>

Subject: Re: Re: Shorter syntax for arrow function assignment

normal functions ... remain necessary for any use case where this needs to be determined at invocation time.

On its way to being an edge case.

On Tue, Oct 24, 2017 at 2:46 PM, Jordan Harband <ljharb at gmail.com <mailto:ljharb at gmail.com> > wrote:

"ES5 functions" - by which you mean, normal functions - are not "outmoded", they remain necessary for any use case where this needs to be determined at invocation time.

Nothing should ever produce an arrow function without =>; and exports assuming const is an interesting idea, but explicit > implicit, and "typing less" is simply not a goal worth optimizing for by itself.

On Tue, Oct 24, 2017 at 11:05 AM, Matthew Robb <matthewwrobb at gmail.com <mailto:matthewwrobb at gmail.com> > wrote:

There is practically no gain to suggest this syntax for arrows anyway as a module has no this binding you are creating a perpetually contextless function whereas using this shorthand syntax for a normal function makes some sense. You lose implicit return regardless.

  • Matthew Robb

On Tue, Oct 24, 2017 at 1:47 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com <mailto:andrea.giammarchi at gmail.com> > wrote:

functions are already outmoded

I don't know where you come from but to me:


// this ain't outmoded at all

const obj = {

  method() { return this === obj; }

};

 

// this ain't outmoded at all

class Any {

  method() { return this instanceof Any; }

}

And a module that provides mixins is definitively not outmoded at all


export method() {

  return this !== undefined;

};

Omitting the arrow is everything but a syntax win here.

On Tue, Oct 24, 2017 at 2:32 PM, Brian Blakely <anewpage.media at gmail.com <mailto:anewpage.media at gmail.com> > wrote:

At current, sans an explicit assignment, the pragma foo() {...} should throw.

On Tue, Oct 24, 2017 at 1:26 PM, dante federici <c.dante.federici at gmail.com <mailto:c.dante.federici at gmail.com> > wrote:

Another annoying thing JS has to deal with is:


// implicitly 'var'

someVar = 10;

So, something like:


myFn() {

}

Would be considered as:


var myFn = function() {

}

with what semantics exist now. Not best practices, but what is currently interpreted in the language.

I'd 100% agree that, as a shorthand, this is nice:


myFn() { }

const myFn = () => {}

Which is what I mean. But I'm not the full implementation of JavaScript.

# Isiah Meadows (6 years ago)

I 100% agree it's a terrible idea, and this proposal's syntax sucks for this very reason.

I'll note a few things:

  1. The main proposal AFAICT is for let foo() {}, not foo() {}.
  2. It does not syntactically conflict with object methods, because it's only valid as a statement.
  3. It conflicts with existing ASI, but only with let and var, where this is currently unambiguously valid (it's open real estate with const):
let
foo
(
x
)
{
}

// Parsed in both sloppy and strict as:
let foo;
(x);
{}
# T.J. Crowder (6 years ago)

On Tue, Oct 24, 2017 at 6:26 PM, dante federici <c.dante.federici at gmail.com> wrote:

So, something like:

myFn() {
}

Would be considered as:

var myFn = function() {
}

with what semantics exist now. Not best practices, but what is currently interpreted in the language.

No, it isn't. It's a SyntaxError: Unexpected token {. There's a big difference between myFn() { } and myFn = function() { }; The latter is valid syntax for the horror of implicit globals (in loose mode; strict mode fixed it). The former is just a syntax error. (It would be valid method syntax if it were inside an object initializer or class.)

But AFAIK, Brian Blakely wasn't promoting that syntax anyway. His original post only ever uses this shorthand with export, so I think it was meant to be specific to exporting.

-- T.J. Crowder

# J Decker (6 years ago)

On Wed, Oct 25, 2017 at 4:57 AM, T.J. Crowder < tj.crowder at farsightsoftware.com> wrote:

On Tue, Oct 24, 2017 at 6:26 PM, dante federici <c.dante.federici at gmail.com> wrote:

So, something like:

myFn() {
}

Would be considered as:

var myFn = function() {
}

with what semantics exist now. Not best practices, but what is currently interpreted in the language.

No, it isn't. It's a SyntaxError: Unexpected token {. There's a big difference between myFn() { } and myFn = function() { }; The latter is valid syntax for the horror of implicit globals (in loose mode; strict mode fixed it). The former is just a syntax error. (It would be valid method syntax if it were inside an object initializer or class.)

ya this is not a syntax error. myFn() { }

# T.J. Crowder (6 years ago)

On Wed, Oct 25, 2017 at 3:11 PM, J Decker <d3ck0r at gmail.com> wrote:

ya this is not a syntax error.

myFn()
{
}

Indeed it isn't, but that isn't what I referred to in dante's message, nor is it what he was suggesting it would be. He quoted

myFn() {
}

...which is indeed a syntax error because ASI doesn't kick in. This:

myFn()
{
}

...isn't a syntax error because ASI adds a ; after myFn(), making it a function call followed by a standalone block, not the function declaration/expression he suggested it was.

All of which is by-the-bye, though, as I don't think Brian was suggesting that anyway... :-)

-- T.J. Crowder

# dante federici (6 years ago)

Sorry I was unclear -- I was referring to "If we were to add this syntax, then seeing this code with knowing how JS interprets the current syntax, I would expect [x] to be the outcome"

I wasn't trying to imply it would work as-is -- either way, sorry for not being clear. If anything the confusion around the newline interacting with the shortened syntax as well as this miscommunication should probably indicate something about the idea.