JavaScript Optional Chaining '?.'
Tags: javascript, node, webdev, tutorial
Published: 2021-02-20 19:37:02

[![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1613713524919/0GDCUBUQX.png)](https://www.sitepoint.com/?ref=osagiebello&utm_source=osagiebello)

---

> The optional chaining `?.` is a safe way to access nested object properties, even if an intermediate property doesn't exist.

Let's assume each user is required to fill an online form of name and address, but users mostly ignored the address input field to submit the form. 

The submitted form of one of the user is modeled as an object as shown below:

```js
const user = { name: 'Bello' }

console.log(user, user.address); // { name: 'Bello' } undefined
```

The `user.address` returns `undefined` because it is not filled by the user.

Let's also assume each `address` object must have a street. In such a case, we get an error. For deeply nested objects, properties, we get an error.

 See example below:


```js
const user = { name: 'Bello' }

console.log(user, user.address.street); 
// TypeError: Cannot read property 'street' of undefined
``` 

What if we don't want that much error but `undefined` for objects that don't exist.

See the example below:

```js
const user = { name: 'Bello' }

console.log(user, user.address ? user.address.street : undefined);
// { name: 'Bello' } undefined
```

What if we have another nested object called `name` as shown below:

```js
const user = { name: 'Bello' }

console.log(
  user, 
  user.address ? user.address.street ? user.address.street.name 
  : null : null
  );
// { name: 'Bello' } null
```

The code snippet above is the same as below:

```js
const user = { name: 'Bello' }

console.log(
user, 
user.address && user.address.street && user.address.street.name
);
// { name: 'Bello' } undefined
```

We do not see the long string of the error in the console, but there is one issue we need to tackle - the repetitive nesting `obj.obj1...objN` or `obj.obj1...objN.propN`.

---

[![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1613864212630/xYCxdavtg.png)](https://partners.hostgator.com/MaZ1N)

---


**Optional chaining** solves the repetitive object nesting issue. The **Optional chaining** above was released in ECMAScript2020.

See the example below:

```js
const user = {name: 'Bello'};

document.write(user, user?.address?.street?.name); 
// [object Object]undefined
```

Note: There must be a variable first like `user` for the example above to work.

> If you are getting an error, an older JavaScript engine is used by your browser. You need to upgrade the browser.

[Edit on Stackblitz](https://stackblitz.com/edit/js-8jhr3x?file=index.html)

Let's make the user object empty below:

```js
const user = { };

document.write(user?.address?.street?.name); 
// undefined
```

The `?.` in an expression can also **short-circuit**. It is like the logical `&&` operator. It finds the first falsy value from left to right and returns it (ignoring any other values after it).

> The optional chaining `?.` is not an operator, but a special syntax construct

See the examples below:

```js
const user = null;

document.write( user?.address ); // undefined
document.write( user?.address.street ); // undefined
```

Recall `null == undefined`

```js
const user = null;
const x = 0;

document.write?.increaseBy1(x++); 
// user value, null is falsy => .increaseBy1(x++) ignored

document.write(x); // 0
```

The construct, `?.` also works on functions.

Syntax:

```js
functionName?.()
```

See the example below:


```js
const userAdmin = {
  admin() {
    document.write("I am admin");
  }
};

const userGuest = { };

userAdmin.admin?.(); // I am admin

userGuest.admin?.(); // no output, no error
```

There's also another optional chaining syntax for retrieving object keys values.

Syntax:


```js
object?.[key]
```

See the example below:

```js
const key = "firstName";

const user1 = {
  firstName: "Osagie"
};

let user2 = null;

document.write( user1?.[key] ); // Osagie
document.write( user2?.[key] ); // undefined
```

Also we can use `?.` with `delete`:

```js
delete user?.name; // ReferenceError: user is not defined
```

> We can use `?.` for safe reading and deleting, but not writing.

See the example below:

```js
const user = null;

user?.name = "John"; // error
```

**Happy coding**

---

[![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1613713705217/uiPmj9ciw.png)](https://buymeacoffee.com/techstackmedia)

---

[![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1613713646252/GDDSdqXof.png)](https://www.datacamp.com/?tap_a=82040-4385c0&tap_s=1301289-aaa316)