45

In Javascript certain operators are processed before others:

1 + 2 * 3
// 1 + (2 * 3)
// 7 because * has higher precedence than +

1 === 0 + 1
// 1 === (0 + 1)
// true because + has a higher precedence than ===

The MDN has a full breakdown of all operators and their precedence ... except await:

await getFoo() * 2; // await (getFoo() * 2) or (await getFoo()) * 2?
await getFoo() === 5; // await (getFoo() === 5) or (await getFoo()) === 5?

(EDIT: The MDN does include await now; it didn't when I originally wrote this question.)

Can anyone explain which operators are processed before/after await?

Right now I feel like I have to add a bunch of parenthesis that are probably unnecessary because I'm not sure what will get handled before/after await. And while I know I should just be able to look this up, even MDN (the gold standard of documentation IMHO) doesn't have the answer.

machineghost
  • 33,529
  • 30
  • 159
  • 234
  • 1
    Interesting. `await` expects an expression after, but gives no clues as to how precedence is handled. Time to experiment. – Nick Jan 12 '18 at 02:36
  • 2
    My understanding is that `await` is treated in the same way as any unary operator. – raina77ow Jan 12 '18 at 02:40

1 Answers1

44

An AwaitExpression is a UnaryExpression and has the same precedence as delete, void, typeof, +, -, ~, and !, binding stronger than any binary operator.

This is unlike yield which has a precedence lower than anything else except the comma operator. This design decision was made because both yield a+b and await a + await b are scenarios thought to be more common than (yield a) + (yield b) and await (a + b).

Rob Johansen
  • 5,076
  • 10
  • 40
  • 72
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 14
    I also fixed MDN :-) – Bergi Jan 12 '18 at 02:54
  • 1
    For operators such as `+`, this makes perfect sense, however, one major pitfall is the use of `&&` with `await`. Consider `await url && fetch(url)`. If `url` is falsy here, we will short-circuit and return the value of `url` (so, typically `undefined`) - that's intended - but if it's truthy, we will proceed to call `fetch(url)` but the expression returns the _promise_ for the fetch call, not the _resolved value_. What you want here is most likely `await (url && fetch(url))`. – JHH May 08 '19 at 10:54
  • 2
    Then again, in most cases `url && await fetch(url)` will do just fine. :) – JHH May 08 '19 at 13:33
  • 2
    @JHH I tend to avoid `await`ing non-thenables in general on principle, since it tends to produce code that's confusing to read, as you have so kindly demonstrated ;) – Patrick Roberts Dec 10 '19 at 19:28
  • 4
    The answer doesn't make clear what operators are preceding `await`. Dot (.) operator has higher priority than `await`. If you have an `async` function called `func` and it returns the object `{prop: 'str'}`, you would have to write `(await func()).prop` to get the property correctly, otherwise `await func().prop` will return `undefined`. – Kutalia Sep 28 '21 at 12:02
  • 1
    @Kutalia I'm not going to reproduce the [entire operator table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table) in this answer, but yes member access is one of the operators with higher precedence than the unary operators. – Bergi Sep 28 '21 at 14:14