New Upcoming JavaScript Features — 2019, 2020 and Beyond

New Upcoming JavaScript Features — 2019, 2020 and Beyond

  • 478

New Upcoming JavaScript Features — 2019, 2020 and Beyond.A peek into the future of the JavaScript language.JavaScript is evolving. Every day, new language ideas and features are discussed and proposed. The TC39 committee is responsible for the specification and development of the ECMAScript (JavaScript) language.

JavaScript is evolving. Every day, new language ideas and features are discussed and proposed. The TC39 committee is responsible for the specification and development of the ECMAScript (JavaScript) language.

TC39 operates by consensus and has the discretion to alter the specification as it sees fit. However, the general process for making changes to the specification is as follows.

Each new language feature has four stages, with each stage representing how far the feature is from being implemented. Stage three features are usually soon to be implemented — but that does not mean they always will be!

This is image title

The TC39 Process — https://tc39.es/process-document/

Let’s take a look at the most promising and exciting stage three features currently being discussed.

Please keep in mind: none of these features are final and all are subject to change. The upside is that if a new feature is to be implemented officially, we’ll already be up to speed and know the how-and-why.

Optional Chaining

When looking for a property value deep in a tree-like structure, one often has to check whether intermediate nodes exist:

const street = user.address && user.address.street;

file.js

checking if the user has an address and street address

Say we’re iterating over an array:

const data = []

data.map(item => <div>{item}</div>)

file.js
looping over data

What happens if the data variable is null or undefined?

We’d get an error like type error: cannot read property ‘data’ of undefined. This usually happens when we fetch data over an API and we’re looping over the data before the request has been finished.

The solution is to check whether our data exists and isn’t empty by checking the array length:

if (data && data.length > 0) {
  data.map(item => <div>{item}<div>)
}
/* or */

data && data.length > 0 &&  data.map(item => <div>{item}<div>)

propChecking.js

It works, but it’s bulky. How can we improve the code above? You may have heard that languages such as TypeScript or Swift have features called optionals.

Optional Chaining to the Rescue

The Optional Chaining Operator allows a developer to handle many of those cases without repeating themselves and/or assigning intermediate results in temporary variables. The Optional Chaining Operator looks like this:

const street = user.address?.street

optional.js

That’s it! A simple question mark to check whether the user has the address property. If they have the address property, access the street property.

Remember the data fetching example? Well, we can improve the code with a simple question mark:

data?.map(item => <div>{item}<div>

optionalMap.js
Check if data exists, and if it does, map over the data.

The call variant of Optional Chaining is useful for dealing with interfaces that have optional methods:

iterator.return?.() // manually close an iterator

optional.js

The Optional Chaining operator is spelled ?.and it may appear in three positions:

obj?.prop       // optional static property access
obj?.[expr]     // optional dynamic property access
func?.(...args) // optional function or method call

optional.js

If you found this feature useful, read the full specifications here. The discussion is open to anyone.

Nullish Coalescing Operator

I know, what a goofy name! Not to worry, it sounds scary but it’s not.

When performing property accesses, it is often desirable to provide a default value if the result of that property access is null or undefined. At present, a typical way to express this intent in JavaScript is by using the || operator:

const response = {
  settings: {
    nullValue: null,
    height: 400,
    animationDuration: 0,
    headerText: '',
    showSplashScreen: false
  }
};

const undefinedValue = response.settings.undefinedValue || 'some other default'; // result: 'some other default'
const nullValue = response.settings.nullValue || 'some other default'; // result: 'some other default'

file.js

This works well for the common case of null and undefined values, but there are several of falsey values which might produce surprising results.

// Potentially unintended. '' is falsy, result: 'Hello, world!'
const headerText = response.settings.headerText || 'Hello, world!'; 

// Potentially unintended. 0 is falsy, result: 300
const animationDuration = response.settings.animationDuration || 300; 

// Potentially unintended. false is falsy, result: true
const showSplashScreen = response.settings.showSplashScreen || true;

file.js

The nullary coalescing operator is better at handling these and serves as an equality check against nullary values such as null or undefined

Syntax

If the expression at the left-hand side of the ?? operator evaluates to undefined or null, its right-hand side is returned:

const response = {
  settings: {
    nullValue: null,
    height: 400,
    animationDuration: 0,
    headerText: '',
    showSplashScreen: false
  }
};

// result: 'some other default'
const undefinedValue = response.settings.undefinedValue ?? 'some other default'; 

// result: 'some other default'
const nullValue = response.settings.nullValue ?? 'some other default'; 

// result: ''
const headerText = response.settings.headerText ?? 'Hello, world!'; 

// result: 0
const animationDuration = response.settings.animationDuration ?? 300;

// result: false
const showSplashScreen = response.settings.showSplashScreen ?? true; 

nullary.js

Here are some key takeaways for the Nullish Coalescing Operator.

  1. The right argument of ?? is evaluated only if needed (“short-circuiting”).
  2. ?? has lower precedence than ||.
  3. ?? cannot immediately contain, or be contained within, an && or || operation.
  4. The right argument is selected if the left argument is null or undefined.

Read the full specification here. Jump into the public discussion here.

BigInt: Arbitrary Precision Integers in JavaScript

If you know JavaScript well enough, you probably know JavaScript is bad at handling numbers. BigInt is an attempt to improve integers for JavaScript.

BigInt is a new primitive that provides a way to represent whole numbers larger than 253, which is the largest number Javascript can reliably represent with the Number primitive:

const x = Number.MAX_SAFE_INTEGER;
// ↪ 9007199254740991, this is 1 less than 2^53

const y = x + 1;
// ↪ 9007199254740992, ok, checks out

const z = x + 2
// ↪ 9007199254740992, wait, that’s the same as above!

numbers.js

A BigInt is created by appending n to the end of the integer or by calling the constructor:

const theBiggestInt = 9007199254740991n;

const alsoHuge = BigInt(9007199254740991);
// ↪ 9007199254740991n

const hugeButString = BigInt('9007199254740991');
// ↪ 9007199254740991n

BigInt.js

Check out the BigInt proposal in-depth right here. If you know Math, please give feedback to the committee.

Static Class Features

This proposal adds three features to JavaScript classes, building on the previous class fields and private methods proposals:

  • Static public fields
  • Static private methods
  • Static private fields

It’s hope that declaring static properties in the class body will be cleaner and do a better job of meeting programmer expectations of what classes should be for.

class CustomDate {
  // ...
  static epoch = new CustomDate(0);
}

/* or */

class CustomDate {
  // ...
}

static.js

Private Fields

To make fields private, just give them a name starting with a #:

class Counter extends HTMLElement {
  #x = 0;

  clicked = () => {
    this.#x++;
    window.requestAnimationFrame(this);
  }

  constructor() {
    super();
    this.onclick = this.clicked.bind(this);
  }

  connectedCallback() { this.render(); }

  render() {
    this.textContent = this.#x.toString();
  }
}
window.customElements.define('num-counter', Counter);

CounterClass.js

Private Methods and Fields

To make methods, getter/setters or fields private, also give them a name starting with a #:

class Counter extends HTMLElement {
  #xValue = 0;

  get #x() { return #xValue; }
  set #x(value) {
    this.#xValue = value; 
    window.requestAnimationFrame(this.#render.bind(this));
  }

  #clicked() {
    this.#x++;
  }

  constructor() {
    super();
    this.onclick = this.#clicked.bind(this);
  }

  connectedCallback() { this.#render(); }

  #render() {
    this.textContent = this.#x.toString();
  }
}
window.customElements.define('num-counter', Counter);

CounterClass.js

Note that this proposal provides private fields and methods only as declared up-front in a field declaration. Private fields cannot be created later, ad-hoc, by assigning to them, the way normal properties can.

You also cannot declare private fields or methods in object literals. For example, if you implement your class based on object literals, or adding individual methods to the prototype, or using a class framework, you cannot use private methods, fields or accessors.

There are many more proposals and I urge you to take a look at them. Everyone has a say, and a vote, your voice matters for shaping the future of the JavaScript language.

See the full list of proposals here.

In case you want to bring your JavaScript game to the next level, I’d suggest grabbing the “You Don’t Know JS” book series. I found it to be easy to understand and useful.

Thanks for reading, stay awesome.