This blog is intended for developers who are familiar with JavaScript development and wants to learn about writing more clean and eloquent getters and setters in JS classes.
Data Integrity
JavaScript is expected to welcome encapsulation to the language soon with the introduction of private
class fields, set to arrive in 2020 as part of ECMAScript 11 release. Feeling the excitement?
Please read my previous blog that describes this in detail: https://ahamedblogs.wordpress.com/2019/11/29/js-encapsulation-before-and-after-classes/
Technically, private class fields declared/defined in a JS class can only be accessed within the scope of that class and can only be accessed and modified indirectly via getters and setters outside the class. This concept is prevalent in many modern OOP languages but it is a brand-new concept to JavaScript.
Note: JS classes do not introduce new object-oriented inheritance model to the language. It merely serves as a syntactic-sugar over existing prototypical inheritance by bringing together the data and behavior.
Example of a JS class utilizing private class fields:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Car { | |
#brand; | |
#model; | |
constructor(brand, model) { | |
this.#brand = brand; | |
this.#model = model; | |
} | |
getBrand() { | |
return this.#brand; | |
} | |
setBrand(brand) { | |
this.#brand = brand; | |
} | |
getModel() { | |
return this.#model; | |
} | |
setModel(model) { | |
this.#model = model; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const car1 = new Car('Tesla', 'Model 3'); | |
car1 instanceof Car; =>//true | |
car1.brand; //=>undefined | |
car1.model; //=>undefined | |
car1.getBrand(); //=>'Tesla' | |
car1.getModel(); //=>'Model 3' | |
//Propery check also fails – no detection. That is exactly what we want. | |
Object.keys(car1); //=>[] | |
'#brand' in car1; //=> false | |
car1.hasOwnProperty('#brand'); //=>false |
As you can see, we can now define/declare instance variables directly inside the class. When variables are prefixed with #
, they are considered private instance fields
and can only be accessed and modified via getters and setters like we have written above. And any attempt to detect private properties using built-in methods will fail.
Crux
In the above example, we have written perfect getters and setters – getBrand
and getModel
to access the private fields. However, there is another shorthand way of writing getters and setters. Introducing this specific-syntax is the crux of this blog. Its usage as follows:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Car2 { | |
#brand; | |
#model; | |
constructor(brand, model) { | |
this.#brand = brand; | |
this.#model = model; | |
} | |
get brand() { | |
return this.#brand; | |
} | |
set brand(brand) { | |
this.#brand = brand; | |
} | |
get model() { | |
return this.#model; | |
} | |
set model(model) { | |
this.#model = model; | |
} | |
} | |
export default Car2; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const car2 = new Car2('Tesla', 'Model 3'); | |
console.log(car2 instanceof Car2); //=>true | |
console.log(car2.brand); //=>'Tesla' | |
console.log(car2.model); //=>'Model 3' | |
car2.brand = 'Ford'; | |
car2.model = 'GT'; | |
console.log(car2.brand); //=>'Ford' | |
console.log(car2.model); //=> 'GT' |
Utilizing this syntax will help access and modify the private fields directly by calling the properties on the object, essentially eliminating the need to invoke getters and setters.
Conclusion
In this blog, we have looked at more eloquently way to write getters and setters in JavaScript. I hope you make use of this in your future projects!
My Github repository containing the above example can be found here: https://github.com/ahamedali95/getters-and-setters-in-JS-classes