Skip to content

Przemysław Konieczniak - Dev Notes

ECMAScript Private Fields

JavaScript, TypeScript

Introduction

Private fields called also private names it's a new feature of ECMAScript specification that at this moment is in Stage 3. As feature name suggests, it allows us to have private fields inside of ECMAScript classes.

We can use class fields in most modern JavaScript runtimes i.e. Node 12, the latest versions of Chrome, and Firefox, TS 3.8.

In this note, I'll focus on the usage with TypeScript.

Syntax

private-fields
1class Foo {
2 bar = 'bar'
3 #baz = 'baz' // private class field
4}
5
6class Bar {
7 bar = 'bar'
8 #baz: string // private class field
9 constructor (baz: string) { this.#baz = baz }
10}
11
12const foo = new Foo()
13foo.bar // bar
14foo.#baz // Property '#baz' is not accessible outside class 'Foo' because it has a private identifier.
15
16const bar = new Bar('bar')
17bar.bar // bar
18bar.#baz // Property '#baz' is not accessible outside class 'Foo' because it has a private identifier.

Use Case

TypeScript provides for us access modifiers (public, protected, private), so why we would be interested in using private fields over private modifier?

  1. Hard privacy

    When we use the access modifiers they support development via static code analysis or during compiler time, but after the compilation properties marked with these modifiers behave like any other properties. It means that JS users can get access to the values of these properties.

    It's worth noticing that the private access modifier doesn't prevent us from getting the value of the field using bracket notation.

    private-modifier
    1class Foo { private foo = 'foo' }
    2const foo = new Foo()
    3console.log(foo['foo']) // foo
    private-fields
    1class Foo { #foo = 'foo' }
    2const foo = new Foo()
    3console.log(foo['#foo']) // undefined and will report an error
  2. Uniqueness in scope class

    private-modifier
    1class A {
    2 private foo = 'foo'
    3 aHelper () { return this.foo }
    4}
    5
    6class B extends A {
    7 private foo = 'baz'
    8 bHelper () { return this.foo }
    9}
    10
    11const b = new B()
    12b.aHelper() // baz
    13b.bHelper() // baz
    private-fields
    1class A {
    2 #foo = 'foo'
    3 aHelper () { return this.#foo }
    4}
    5
    6class B extends A {
    7 #foo = 'baz'
    8 bHelper () { return this.#foo }
    9}
    10
    11const b = new B()
    12b.aHelper() // foo
    13b.bHelper() // baz

Summary

In opposite to the private modifier, private fields are really private and their behavior is more predictable.

There are also some things worth noticing.

Because fields with private modifier after the compilation are treated as other properties, access to them can be faster in some runtimes than accessing private fields.

TypeScript's private fields support only ES6 target or higher and private fields work even with EcmaScript 3.

Resources

© 2020 by Przemysław Konieczniak - Dev Notes. All rights reserved.