# JS Tip of the Day: Missing Semicolon ASI Gotchas

**URL:** <https://forum.kirupa.com/t/js-tip-of-the-day-missing-semicolon-asi-gotchas/643168>\
**Category:** web dev\
**Created:** [February 28, 2020, 1:37pm UTC](https://forum.kirupa.com/t/js-tip-of-the-day-missing-semicolon-asi-gotchas/643168 "2020-02-28T13:37:07Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [February 28, 2020, 1:37pm UTC](https://forum.kirupa.com/t/js-tip-of-the-day-missing-semicolon-asi-gotchas/643168/1 "2020-02-28T13:37:07Z")

</div>

**Missing Semicolon ASI Gotchas**  
Level: Intermediate

For the most part, semicolons used for marking the end of a line of code are optional in JavaScript. If not added by you explicitly, they’ll be added for you automatically. This process is known as Automatic Semicolon Insertion, or ASI for short. If you wish to rely on ASI for your code rather than adding semicolons yourself, you should be aware of the following gotchas where ambiguity can cause ASI to behave unexpectedly, specifically where it is not inserting a semicolon when you might expect it to.

**When a line starts with `[`** _bracket access or array literal?_

Consider the following:

```javascript
let x = 1
[1,2,3].indexOf(x)
// TypeError: Cannot read property 'indexOf' of undefined

```

You might expect `[1,2,3]` to be an array literal, starting a new statement below the declaration of the `x` variable above it. However, in this case ASI does not add a semicolon after the first statement, so when executed, this code is seen as:

```javascript
let x = 1[1,2,3].indexOf(x)

```

This then causes the square brackets to be seen as bracket access notation for the `1` which, in turn, treats the values inside as a comma-separated list resolving the last value in that list or `3`. What you get is `1[3].indexOf(x)` or, since Number values do not have a `3` property, `undefined.indexOf(x)` which causes the error.

This is a case where, to prevent this from happening, you would need to explicitly provide a semicolon after the first statement because ASI was not providing one for you.

```javascript
let x = 1;
[1,2,3].indexOf(x) // 0

```

Now, the declaration of `x` is correctly terminated at the `1` and `[1,2,3]` is seen as an array literal. This means `indexOf()` will correctly be called from an array value rather than undefined.

ASI here, and in additional examples outlined below, can’t tell from the line following the declaration of `x` whether or not it is supposed to be used with the previous line or not since it would be valid syntax (despite possibly throwing a runtime error) in either case. What it ends up deciding to do is not including an automatic semicolon - something which may actually be right in some cases. It just happens not to be right in this case.

Starting a line with an array literal is one of the more likely circumstances you might run into this, but there are a few others as well…

**When a line starts with `(`** _function call or grouping?_

```javascript
let x = 1
(() => x)()
// TypeError: 1 is not a function

```

Here, the first set of parenthesis containing the function are treating 1 like a function, calling it as `1(() => x)`. With an explicit semicolon, the parens are a group wrapping the function rather than being seen as a function call:

```javascript
let x = 1;
(() => x)() // 1

```

**When a line starts with `/`** _division or RegExp literal?_

```javascript
let x = 1
/abc/i
// ReferenceError: abc is not defined

```

This is being seen as the division of the values `1 / abc / i`, but since `abc` (or whatever other character string you might have in a regular expression) is not a defined variable, we get an error. With a semicolon, the forward slashes are seen as the start of a regular expression literal:

```javascript
let x = 1;
/abc/i // /abc/i

```

**When a line starts with ```** _tagged template literal or template literal?_

```javascript
let x = 1
`text`
// TypeError: 1 is not a function

```

Here, `1` is being seen as a template tag (which should be functions) for the template literal below it. With a semicolon, its an untagged template string:

```javascript
let x = 1;
`text` // "text"

```

**When a line starts with `+`** _unary `+` or addition?_

```javascript
let x = 1
+'1'
// x = "11"

```

This is one statement assigning `x` to `1 + '1'`. With a semicolon, there’s two statements, the second being a unary + which converts the string “1” to the number `1`:

```javascript
let x = 1;
+'1' // 1
// x = 1

```

**When a line starts with `-`** _unary `-` or subtraction?_

```javascript
let x = 1
-'1'
// x = 0

```

This assigns `x` to `1 - '1'`. The semicolon again allows separation, with the second statement being a unary - which converts the string “1” to the number `-1`:

```javascript
let x = 1;
-'1' // -1
// x = 1

```

More info:

- [Automatic Semicolon Insertion on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Automatic_semicolon_insertion)
