JavaScript Public Class Fields

By

Learn how JavaScript public class fields let you declare a field like count = 0 directly in the class body, instead of setting it inside the constructor.

~~~

Public class fields let you declare and initialize a property directly in the class body, without writing a constructor.

In the past, to create a public class field we would have used this syntax, instantiating the field in the constructor:

class Counter {
  constructor() {
    this.count = 0
  }
}

The new class fields proposal, which you can use since Chrome 72 and Node 12, allows us to use this syntax:

class Counter {
  count = 0
}

Much simpler!

The proposal has since been finalized: class fields are officially part of the language, standardized in ES2022.

How do fields behave?

Each instance gets its own copy. The initializer runs every time you call new, before the constructor body.

You can still have a constructor, and a field initializer can use fields declared above it, through this:

class CartItem {
  price = 3
  quantity = 4
  total = this.price * this.quantity
}

new CartItem().total //12

Fields initialize top to bottom, so total sees price and quantity already set. Flip the order and total would be NaN, because the other two fields don’t exist yet.

Fields holding arrow functions

A common pattern is assigning an arrow function to a field:

class Counter {
  count = 0

  increment = () => {
    this.count++
  }
}

Arrow functions don’t have their own this, they take it from where they’re defined. Here that’s the field initializer, where this is the instance. So increment stays bound to its instance no matter how you call it, which is handy when passing it around as a callback or event handler.

One thing to watch

There’s a cost to that pattern. A regular method lives on the prototype and is shared by every instance. A field holding an arrow function lives on each instance, so every new Counter() creates a fresh copy of the function.

With a handful of instances it makes no difference. If you create thousands of them, all those duplicate functions add up in memory.

My advice: use regular methods by default, and reach for the arrow function field only when you actually need the binding.

~~~

Related posts about js: