Back Copy 3 back
image

Private variables (fields), private methods, private accessors. Javascript finally gave “some privacy” to classes

Nikola Tasikj July 23, 2020
share this on

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.

Credits

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 the jack 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.