Fundamentals 15 min read

Class Fields Reach Stage 4 – How This Changes JavaScript Development

The article reviews the recent TC39 meeting where the Class Fields proposal advanced to Stage 4, outlines the criteria for moving between proposal stages, and summarizes several other ECMAScript proposals—including Intl.LocaleInfo, Object.hasOwn, Symbol as WeakMap keys, extended timezone options, copy‑based array methods, and readonly ArrayBuffer—detailing their goals, status, and example code.

Alibaba Terminal Technology
Alibaba Terminal Technology
Alibaba Terminal Technology
Class Fields Reach Stage 4 – How This Changes JavaScript Development

In this meeting, the highly‑watched Class Fields proposal finally advanced to Stage 4, becoming part of the ECMAScript standard.

Stage 3 → Stage 4

Moving from Stage 3 to Stage 4 requires:

Writing tc39/test262 tests that cover the proposal and merging them into test262.

At least two implementations passing the Test262 suite and shipping in a formal release.

Submitting a pull request that incorporates the proposal into the official ECMA‑262 text and obtaining the ECMA‑262 editor’s sign‑off.

Relevant repositories:

https://github.com/tc39/test262

https://github.com/tc39/ecma262

Class Fields

Proposal links:

https://github.com/tc39/proposal-class-fields

https://github.com/tc39/proposal-private-methods

https://github.com/tc39/proposal-static-class-features

Before the proposal, class fields had to be created inside the constructor, which is not declarative and makes code harder to read. The new syntax lets developers declare fields directly on the class, improving readability and enabling more robust API designs.

JavaScript engines also expose many internal slots (e.g., [[MapData]]) that are only accessible from the engine. The proposal brings a similar mechanism to pure JavaScript, allowing library and runtime authors to create private fields safely.

Example (TypeScript with useDefineForClassFields):

class Base {
  name: string;
  constructor() {
    this.initProps();
  }
  initProps() {
    this.name = 'xxx';
  }
}
class Derived extends Base {
  age: number;
  initProps() {
    super.initProps();
    this.age = 10;
  }
}
const d = new Derived();
console.log(d.age);

Stage 2 → Stage 3

Requirements for moving from Stage 2 to Stage 3:

Writing a complete standard text reviewed and signed by a TC39 member.

Obtaining the ECMA‑262 editor’s sign‑off.

Intl.LocaleInfo

Proposal adds APIs to Intl for retrieving user locale preferences such as the first day of the week, weekend definition, and text direction.

let zhHans = new Intl.Locale("zh-Hans");
zhHans.weekInfo; // {firstDay: 1, weekendStart: 6, weekendEnd: 7, minimalDays: 4}
zhHans.textInfo; // {direction: "ltr"}

Object.hasOwn

The proposal introduces Object.hasOwn as a safer alternative to Object.prototype.hasOwnProperty, avoiding issues when the method is overridden.

let object = { foo: false };
Object.hasOwn(object, "foo"); // true
let object2 = Object.create({ foo: true });
Object.hasOwn(object2, "foo"); // false
let object3 = Object.create(null);
Object.hasOwn(object3, "foo"); // false

Symbol as WeakMap Keys

This proposal allows Symbol values to be used as keys in WeakMap, enabling weak references to objects via symbols and supporting use‑cases in Records & Tuples.

class RefBookkeeper {
  #references = new WeakMap();
  ref(obj) {
    const sym = Symbol();
    this.#references.set(sym, obj);
    return sym;
  }
  deref(sym) { return this.#references.get(sym); }
}
globalThis.refs = new RefBookkeeper();
const server = {
  port: 8080,
  handler: refs.ref(function handler(req) { /* … */ })
};
refs.deref(server.handler)({ /* …req */ });

Extend Timezone Options

The proposal expands the timeZoneName option of Intl.DateTimeFormat with additional formats such as shortOffset, longWall, etc.

let timeZoneNames = ["short","long","shortOffset","longOffset","shortWall","longWall"];
timeZoneNames.forEach(name => {
  console.log(new Date().toLocaleTimeString("zh-Hans", {timeZoneName: name}));
});

Change Array By Copy

To support immutable data structures like Tuple, this proposal adds non‑mutating copies of array‑mutating methods (e.g., sorted()) so that the original array remains unchanged.

let arr = [3,2,1];
arr.sort(); // arr becomes [1,2,3]
arr = [3,2,1];
let sorted = arr.sorted(); // sorted is [1,2,3], arr stays [3,2,1]

Readonly ArrayBuffer & ArrayBufferView

The proposal adds a freeze -like capability to ArrayBuffer and its views, preventing writes to the underlying memory.

const buffer = new ArrayBuffer(4);
const view = new Int32Array(buffer);
view[0] = 42; // OK
buffer.freeze();
view[0] = 42; // TypeError
buffer.isFrozen(); // true

All of these proposals are already implemented in environments such as Chrome 74, Node 12, Safari Technology Preview 117, TypeScript 3.8, and Babel 7+, though some implementations may differ before the final standard is locked.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptECMAScriptlanguage featuresTC39Class Fieldsproposals
Alibaba Terminal Technology
Written by

Alibaba Terminal Technology

Official public account of Alibaba Terminal

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.