Skip to content

Instantly share code, notes, and snippets.

@OliverJAsh
Last active May 31, 2021 07:25
Show Gist options
  • Save OliverJAsh/71cfca924b4cd144b57a764d7fb1cdff to your computer and use it in GitHub Desktop.
Save OliverJAsh/71cfca924b4cd144b57a764d7fb1cdff to your computer and use it in GitHub Desktop.
JavaScript function declarations vs. expressions

JavaScript function declarations vs. expressions

Declarations

Pros

  • Sync/async generator forms

Cons

Subjective

  • Hoisting

Expressions

Pros

  • Arguably simpler, same construct for creating values regardless of type (var, const, let)
  • Can use with TypeScript type annotations e.g. const reducer: Reducer = () => {}
  • Automatic this binding (not to encourage use of this, though…)
  • More concise thanks to arrow syntax
  • If you want to use function composition i.e. flow, you have to use an expression. Furthermore, TypeScript can infer types of composed functions, e.g. const aToC = flow(a, b, c); // (a: A) => C.

Cons

  • No sync/async generator forms

Subjective

  • No hoisting

The thing I personally dislike about hoisting is it doesn't enforce any direction in the code. Definitions may appear above or below. Without hoisting, it's always one direction: details -> derived values.

@MartinJohns
Copy link

Can use with TypeScript type annotations e.g. const reducer: Reducer = () => {}

A subjective con about this is that it's often used without additional type annotations for the return type, resulting in excess property checks not kicking in.

@OliverJAsh
Copy link
Author

OliverJAsh commented May 14, 2021

Good point. Reduced test case for reference:

type Result = { foo: string };
type Fn = () => Result;
const fn: Fn = () => ({
    foo: 'f',
    // no error ❌
    a: 2,
});
const fn2: Fn = (): Result => ({
    foo: 'f',
    // error ✅
    a: 2,
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment