Lawrence Vo Lawrence Vo - 1 month ago 10
Javascript Question

Javascript Syntax - Arrow function for class

After doing some tutorials online, I stumbled upon some weird JavasSript syntax that I'm not familiar with. In this tutorial, the author does this

export default ComposedComponent => class extends


Can someone explain to me what it means? It looks like a fat arrow function but there doesn't seem to be any arguments. it is also multilined but there are no brackets. What does this exactly mean?

Answer

It is an arrow function, and it does have an argument (ComposedComponent). It is also "multi-lined", but it's a single statement, ergo it does not need brackets.

export default ComposedComponent => class extends
Component {
  // ...
}

is every bit the same as

export default ComposedComponent => class extends Component { ... }

And the class which is returned is anonymous class X extends Component.


edit

to expand upon the comments below:

There are three things going on, on that one line, which might cause confusion.

export default (ComposedComponent) => {
  return class UnnamedClass extends Component {
    render () {
      return <ComposedComponent />;
    }
  };
}

written in this fashion it should be easier to see what's going on.

  1. export statement, exporting a function

  2. an arrow function with one argument and a body which is just a return statement (whether the statement is split across lines or not)

  3. an anonymous class is constructed

As you know, arrow functions don't need parentheses when they have one argument, nor do they need braces when they only have a return statement.

x => x;

That's true, even if the return statement spans multiple lines which can't have semicolon insertion.

() => "1" +
      "2" +
      "3";

Which is where

() => class extends
Component {
  // ...
}

comes in...

That's not how I'd write it, but there it is. I'd probably prefer to do:

() => class extends Component {
  // ...
}

to match the JS we're all used to (though decorators and TS may change that).

The last part is important. Classes are happily anonymous, unless you put them in a position where they need a name.
And if you think about it, that makes complete sense. They're really just cleaned-up versions of constructor functions from yesteryear, and have nothing to do with classes in most other languages.

const X = class { constructor () { } };
const x = new X();

is no different than saying

const X = function () { };
const x = new X();

so

class X {
  constructor () { }
}

and

function X () { }

are equivalent.

Anywhere you could pass a function, with the expectation that somebody will new it, you could pass an anonymous class.

makeInstance(class {
  a () { }
  b () { }
});

Tie that all together, and you get

export default ComposedComponent => class extends
Component {
  render () {
    return (
      <ComposedComponent >
       // ...
      </ComposedComponent>
    );
  }
}