Private methods proposal, as a part of the class fields proposal has been promoted to Stage 4 in the TC39 process and will be officially included in ECMAScript 2022!
In this blog, we will cover private class features which will be a part of ECMAScript 2022.
Before
By default, all properties in ES6 classes are public and can be examined or modified outside the class. In the example below, we find that there is nothing in the class to prevent the property from being changed without calling the setter.
class TimeTracker {
name = 'Alice';
project = 'blog';
hours = 0;
set addHours(hour) {
this.hours += hour;
}
get timeSheet() {
return `${this.name} works ${this.hours || 'nothing'} hours on ${this.project}`;
}
}
let person = new TimeTracker();
person.addHours = 2; // standard setter
person.hours = 4; // bypass the hours setter altogether
person.timeSheet; // Alice works 4 hours on blog.
After
Starting from ECMAScript 2022,
private class fields are defined using a hash #
prefix,
From the above example,
we can modify it to include a private class field
to prevent the property from being changed outside of the class method.
class TimeTracker {
name = 'Alice';
project = 'blog';
#hours = 0; //private class field
set addHours(hour) {
this.#hours += hour;
}
get timeSheet() {
return `${this.name} works ${this.#hours || 'nothing'} hours on ${this.project}`;
}
}
let person = new TimeTracker();
person.addHours = 4; // standard setter
person.timeSheet // Alice works 4 hours on blog
When we try to modify the private class field outside of the setter method, we get the error -
person.#hours = 4 // Error Private field '#hours' must be declared in an enclosing class
We can also make methods or getter/setters private,
by giving them names starting with #
.
class TimeTracker {
name = 'Alice';
project = 'blog';
#hours = 0; //private class field
// private method (can only be called within the class)
set #addHours(hour) {
this.#hours += hour;
}
get #timeSheet() {
return `${this.name} works ${this.#hours || 'nothing'} hours on ${this.project}`;
}
constructor(hours) {
this.#addHours = hours;
console.log(this.#timeSheet);
}
}
let person = new TimeTracker(4); //Alice works 4 hours on blog
Private class features are under development or implemented in below -
- Babel by Tim McClure
- In progress in TypeScript by Bloomberg
- Shipping in V8
Notes:
- Private fields and methods must be declared up-front in the field declaration.
- Private fields cannot be created ad-hoc through the assignment.
Check out more details in the private methods proposal.