By Valentino Gagliardi

Translation: Crazy geek

Original: www.valentinog.com/blog/privat…

Reproduced without permission

In this article, we’ll take a look at JavaScript private class fields and see how they differ from TypeScript private modifiers.

JavaScript private class fields and privacy requirements

In the past, JavaScript had no native mechanism to protect variables from access, except, of course, for typical closures.

Closures are the basis for many similar proprietary patterns in JavaScript, such as the popular module pattern. However, with the introduction of ECMAScript 2015 classes in recent years, developers have felt the need for more control over the privacy of class members.

The Class field proposal (in phase 3 at the time of this writing) attempts to solve the problem by introducing private class fields.

Let’s see what they look like.

Example of a JavaScript private class field

This is a JavaScript class with private fields. Note that, unlike “public” members, each private field must be declared before it is accessed:

class Person { #age; #name; #surname; constructor(name, surname, age) { this.#name = name; this.#surname = surname; this.#age = age; } getFullName() { return `${this.#name} + ${this.#surname}`; }}Copy the code

Private class fields cannot be accessed from outside the class:

class Person {
  #age;
  #name;
  #surname;
  constructor(name, surname, age) {
    this.#name = name;
    this.#surname = surname;
    this.#age = age;
  }
  getFullName() {
    return `${this.#name} + ${this.#surname}`;
  }
}
const marta = new Person("Marta", "Cantrell", 33);
console.log(marta.#age); // SyntaxError
Copy the code

This is truly “private”. If you know a bit about TypeScript, you might ask what “native” private fields have in common with private modifiers in TypeScript.

Well, the answer is: no. But why?

The private modifier in TypeScript

Developers with a background in traditional programming languages should be familiar with the private qualifier in TypeScript. In short, the purpose of this keyword is to deny access to a class member from outside the class.

But don’t forget that TypeScript is a layer on top of JavaScript, and the TypeScript compiler should strip all the fancy TypeScript comments, including private.

This means that the following classes won’t do the job you want them to:

class Person {
  private age: number;
  private name: string;
  private surname: string;
  constructor(name: string, surname: string, age: number) {
    this.name = name;
    this.surname = surname;
    this.age = age;
  }
  getFullName() {
    return `${this.name} + ${this.surname}`; }}const liz = new Person("Liz"."Cantrill".31);
// @ts-ignore
console.log(liz.age);
Copy the code

Without //@ts-ignore, accessing Lizzie. Age only raises errors in TypeScript, but when compiled, you get JavaScript code like this:

"use strict";
var Person = /** @class */ (function () {
    function Person(name, surname, age) {
        this.name = name;
        this.surname = surname;
        this.age = age;
    }
    Person.prototype.getFullName = function () {
        return this.name + "+" + this.surname;
    };
    returnPerson; } ());var liz = new Person("Liz"."Cantrill".31);
console.log(liz.age); / / 31
Copy the code

As expected, we can output liz.age from the console. The main point here is that private in TypeScript is not that private and is only convenient at the TypeScript level, not “real private.”

Let’s start with TypeScript’s “native” private class fields.

Private class fields in TypeScript

TypeScript 3.8 will support ECMAScript private fields, not to be confused with TypeScript private modifiers.

This is a class with private class fields in TypeScript:

class Person {
    #age: number;
    #name: string;
    #surname: string;
    constructor(name:string, surname:string, age:number) {
        this.#name = name;
        this.#surname = surname;
        this.#age = age;
    }
    getFullName() {
        return `${this.#name} + ${this.#surname}`; }}Copy the code

There is no difference from native JavaScript except for type comments. Members cannot be accessed externally. But the real problem with private fields in TypeScript is that they use WeakMap behind the scenes.

To compile this code, we need to adjust the target compilation version in tsconfig.json, which must be at least ECMAScript 2015:

{
  "compilerOptions": {
    "target": "es2015"."strict": true."lib": ["dom"."es2015"]}}Copy the code

Depending on the target browser, this can be problematic, and unless you plan to polyfill WeakMap, it becomes too much work just to write nice new syntax.

There’s always this tension in JavaScript, you do want to use the new syntax, but on the other hand, you don’t want to affect the user experience with a lot of polyfills.

On the other hand, even if you want to publish it to newer browsers, you don’t have to worry about private class fields. At least for now. Even Firefox doesn’t implement this advice.

conclusion

As of this writing it is still a proposal, JavaScript class fields are interesting, but browser vendor support is poor. So what do you think of this feature?

This is mine:

  • I like the ES private class field (although I don’t#)
  • I never rely on private in TypeScript, which is only useful at the TS level
  • I wait for the browser to provide the private class field
  • I won’t use private class fields in TS for now

Learn more about TypeScript class information: www.typescriptlang.org/docs/handbo…

The TypeScript 3.8 private fields of the official announcement: devblogs.microsoft.com/typescript/…

Welcome to pay attention to the front end public number: front end pioneer, free front-end engineering utility kit.