
Private fields are supported by Google Chrome v74+ and NodeJs 12+
Private methods and accessors are supported by Google Chrome v84+
Day by day, we are all witnessing the rapid progress of Javascript. There are still some mind blowing things that your non-javascript colleagues will joke about, but days without having private fields in classes are far behind us.
In March last year, V8 (Google’s Javascript engine) was upgraded with private fields in classes. From that moment we are stepping forward in respecting Encapsulation. Defining classes with private fields is done by prepending it with a # prefix. This syntax was part of global criticism because other languages are using private for the same thing and it looks like a hack, but for now, there is no info that this will be changed in the future.
Private variables (fields)
Defining private fields in class (and using them in object — instance for that class) means accessing that field will be allowed only to the current object (inside that same class). Setting value for that variable or getting it needs to be done by setter and getter. I guess that this old part is already routine for you, but let me show you one simple example of how private fields work in javascript. If you want to create a class with private fields, you should use:
class Person { #name #age }
In this class as you can see I prepend # on those 2 variables. This will create 2 variables: name and age that will be private. If you try to create an object from this class and then access any of these two variables it will throw an error.
Keep in mind that # is part of that private variable and the way how javascript recognizes private fields at the same time. Setting a name with
jack.name = ‘Jack'
will still allow you to create a new field inside thejack
object that will be public, but this is NOT the way how you want to use classes.
We created a class, but it’s useless for us because it has 2 private fields that are undefined
and we can’t do anything with them. I mentioned that we need setters and getters to make this class useful, so let’s do that.
Now we have a fully functional class and we can construct it using let x = new Person('Jack', 22)
, after that, we can take name or age with getters using x.name
or x.age
. Also, if we want to change the value we can do that with class setters x.name = 'New name'
or x.age = 23
. Don’t be confused about this syntax. As you know from the image before we tried to access private members with x.#name
and now we are using x.name
this is correct and it’s because now we have getter with the same name in a class that is public (we will also have an example with private accessors), so we are calling it as we defined it, if we defined that getter as giveMeName
we should call it with x.giveMeName
.
Be careful with naming getters and setters, in practice they should have the same name as the field they are created for. Calling x.name
without getter will give you undefined
because you don’t have an accessor, method or field with that name, but calling x.name = 'New name'
without setter will create you new public field in that object, you will be confused and that may also result in getting wrong value if you call x.name
after it, where you will think that you are accessing private #name
field, but you will access the newly created public field name
.
Private accessors
Private accessors arrived in Javascript with a new V8 update that was on 30 June this year. Be careful with using this, because for now, they are only available on Google Chrome v84+. Accessors are simply getters and setters that can be now defined as private. The syntax for creating private accessor is the same as for field, it’s using # before the name. When private fields were added (1 year ago) they gave us a note that private accessors and methods are in the test phase and they are coming if we want to use them in the future to prepend #
on their names, so if you did that into your code now you will have them as private. If we want to upgrade some of our previous accessors to be private, we can do it by defining it like:
get #privateAge() { return this.#age; }
Keep in mind that you should not have getter with the same name as a variable. So if we just prepend #
to our previous getter we will have an error about the same name, because our private field is also called #age
, so you need to give it another name. Same as private fields, these accessors can be called only inside that class, so using this type of private getters will be rare but good to have.
Private methods
The story will not be whole if we don’t have private methods in it. Same as accessors, they arrived with the newest V8 update and they are available only on Google Chrome v84+. Methods are a really important part of creating classes, most of them are used only inside the class, but we couldn’t make them private before this new update. Defining private methods is the same as previous, just prepending # on the method’s name.
#method() { console.log("Private method!"); }
We can define as much as we want methods with different names and they can be called simply with x.#method
, but they will be callable only from inside.
These new features will be really helpful and useful in Javascript. Finally, we can be more secure, we will have fewer errors if someone tries to change our private fields and we can tell that Javascript now has full Encapsulation, without faking private variables with closures.