Y U NO USE the JS native APIs?
Tags: javascript, webdev, productivity, programming
Published: 2023-01-14 15:36:19

Maybe you’re stuck in the ES5 or under a rock for a long time… basically the same thing.

But JS gets more toys for us to use basically every year, with a lot more to come. And since I know people that aren’t using it, I’ll try to highlight here some of the APIs that I can’t live without anymore.

## 2020

### Nullish coalescing operator (`??`)

You might know the AND (`&&`) and OR (`||`) operators, but you know that one case like:

```tsx
let number = null; // zero being a valid number
// something happens
number = 0;

// check if it's false
if (!number) {
	throw new Error('oops, zero is also falsy!');
}

// this will check if it's null or undefined
if(number ?? true){
	throw new Error('now, only null or undefined will throw!')
}

// usually you would use like
const myPossibleNullishValue = someValue ?? 'value if null or undefined'

// you can also do this:
function ItsAError(){ throw new Error("it's a me, error!") }
const myPossibleNullishValue = someValue ?? ItsAError();
// this way you can validate if the value is not null or undefined as you assign it.
```

### Optional chaining (elvis operator, `?.`)

No more `object && object.prop1 && object.prop1.prop2 ...` 

```tsx
const object = {};

// ok, so: as long as object exists, then object.anything won't throw
// object.anything will be undefined if anything doesn't exists, but that's it
// object.anything.anotherThing however, this will throw because anything is undefined
// all this to say that, you start chaining from the objects that may not exist
const myValue = object
  .prop1
  ?.anything
  ?.anotherThing
  ?.prop2 ?? 'combine with nbullish coalescing for when the value is undefined!';

// it doesn't end here!
// you can chain multiple things:
const test = {
  arr: [1, 2, 3, 4],
  function: () => 'hello!',
  obj: {
    something: 'else'
  }
}

// arrays
test.arr?.[0] ?? 'oops' // 1
test.notArr?.[0] ?? 'oops'; // oops

// functions
test.function?.() ?? 'oops' // hello!
test.notFunction?.() ?? 'oops' // oops

// objects
test.obj?.['something'] ?? 'oops' // else
test.notObj?.['something'] ?? 'oops' // oops
```

## 2021

### Promise.any

I’m sure you already had to use `Promise.race`, but sometimes you don’t care that one promise fails, you just want the first that actually resolves. In this case, you use `Promise.any`.

```tsx
const maybe = async (n) => {
  const random = Math.random() > 0.8;
  return Promise[random ? 'resolve' : 'reject'](random ? `yes! ${n}` : `nope =/ ${n}`)
};

const coisa = await Promise.any([
  maybe(1),
  maybe(2),
  maybe(3),
  maybe(4),
])
  .then(val => {
    // on the first one that resolves...
    console.log(val) // yes! n
  })
  .catch(err => {
  // if all fails...
  console.log(err.errors) // [ 'nope =/ 1', 'nope =/ 2', 'nope =/ 3', 'nope =/ 4' ]
});
```

### Number separators (`_`)

What’s this number: `123456789`?

How about this: `123_456_789`?

That’s it. Just a little quality of life for developers, if you’re using big numbers, you can use the separator to be easier to read.

BTW… this is also valid: `1_2_3_4_5_6_7_8_9` but, for obvious reasons, don’t do that! As long as you don’t use it before/after the number it’s valid. So make sure to put the separator in the right place, please!

### String.replaceAll

While we all love RegExp, sometimes we really don’t need to pull out the big guns…

```tsx
'abbbaab'.replaceAll('b', 'x') // 'axxxaax'
```

## 2022

### Classes: private and static

Functional is all the rage right now, but sometimes you need an old but still good class… well, it’s better than ever to work with classes in vanilla JS.

Static values and functions are those that live outside of any object instance. It’s something global and has many uses.

And now we have true private fields and functions. You might have seen and used `_underscores` to say to others that something was to be private, now you can just use `#` and have it truly be private.

```tsx
class Counter {
  static #privateTotal = 0

  constructor() {
    Counter.#add();
  }

  static #add() {
    Counter.#privateTotal++;
  }

  remove() {
    Counter.#privateTotal--
  }

  static get total() {
    return Counter.#privateTotal
  }

}

const number1 = new Counter();
const number2 = new Counter();
const number3 = new Counter();
const number4 = new Counter();
Counter.total2 //?
const number5 = new Counter();
console.log(Counter.total); // 5
number1.remove();
console.log(Counter.total); // 4

Counter.add(); // not a function
Counter.#add(); // SyntaxError: Private field '#add' must be declared in an enclosing class
console.log(Counter.privateTotal); // undefined
console.log(Counter['#privateTotal']); // undefined
console.log(Counter.#privateTotal); // SyntaxError: Private field '#privateTotal' must be declared in an enclosing class
```

### String/Array.at

You probably with calluses from doing `arr[arr.length -1]` for when you want the last element or something like that… well, no more:

```jsx
const arr = [1, 2, 3, 4, 5]
const str = 'hello world'

console.log(arr.at(-1)) // 5
console.log(str.at(-1)) // d
```

This is so simple, yet so good. Satisfying!

## So… Y U NOT using them?

If you have any transpiling step in your process, then you just have to check for you to use the new APIs and if any aren’t compatible with your target environment, then it will either polyfill or just translate to an uglier, more verbose version of the same thing.

For us, developers, we can just use the newest toys and just let the compilers do their thing to support whatever toaster or palmtop running your code.

Now, tell me which ones you’re already using and which ones you’re now facepalming yourself for not using till now.