Deep dive into public and private instance fields in JavaScript (ECMAScript 2022)

0
114
Saeloun Logo


The class fields proposal
expands the existing JavaScript class syntax with new functionality.
This new functionality has been promoted to Stage 4 in
the TC39 process
and will be officially included in ECMAScript 2022.

In this blog, we will look into public and private instance class fields in detail.

Public instance fields

Public class fields allow us to add instance properties
to the class definition with the assignment operator (=).

Before

Consider a simple React component of incrementing the count.

import React, { Component } from "react";

export class Incrementor extends Component {
  constructor() {
    super();
    this.state = {
      count: 0,
    };
    this.increment = this.increment.bind(this);
  }

  increment() {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <button onClick={this.increment}>Increment: {this.state.count}</button>
    );
  }
}

In this example, we define instance fields and bind methods in the constructor.
We can make the code a little more intuitive by using the new class syntax.

After

The new public class fields syntax allows us to add instance properties
directly as a property on the class without
having to use the constructor method.
This simplifies the class definition
making the code look pretty readable with less boilerplate!

import React from "react";

export class Incrementor extends React.Component {
  state = { count: 0 };

  increment = () => this.setState({ count: this.state.count + 1 });

  render = () => (
    <button onClick={this.increment}>Increment: {this.state.count}</button>
  );
}

Now, a lot of people reading this are probably thinking
“Well, we’ve been able to do this in JavaScript for ages”,
which is true.
But,
it is not standard ECMAScript
and isn’t enabled by default.
If the project is created using create-react-app,
it is enabled by default or else we have to include the right
Babel plugin.
However,
Babel 7.14 enables class fields & private methods by default
in @babel/preset-env.

Let’s check out more about public instance fields.

  • Public instance fields exist on every created instance of a class.
    They are added with Object.defineProperty()
    either at construction time in the base class (before the constructor body runs)
    or just after super() returns in a subclass.
class Incrementor {
  count = 0
}

const instance = new Incrementor();
console.log(instance.count);
// expected output: 0
  • Fields, which are not initialized are set to undefined.
class Incrementor {
  count
}

const instance = new Incrementor();
console.assert(instance.hasOwnProperty('count'));
console.log(instance.count);
// expected output: "undefined"
  • Like properties, field names may be computed.
const PREFIX = 'main';

class Incrementor {
  [`${PREFIX}Count`] = 0
}

const instance = new Incrementor();
console.log(instance.mainCount);
// expected output: 0

Private instance fields

Private fields are accessible on the class constructor
from inside the class declaration itself.
When we want to prevent people from accessing the property directly
private class fields should be used.

Private fields are based on syntax using a #,
both when declaring a field and when accessing it.

class Incrementor {
  #count = 0;
  fetchCount() {
    console.log(this.#count);
  }
}

const instance = new Incrementor();
console.log(instance.fetchCount()); // 0
instance.#count === 42;   // Syntax error

Check out more details
about the private instance fields in our previous blog.

See
the private syntax FAQ
for discussion of alternatives considered and the constraints that led to this syntax.



Source link

Leave a reply

Please enter your comment!
Please enter your name here