Other notable features

JavaScript classes give us a bunch of nice features that make the code we write clean and concise, while also performing at or near the same speed as if we wrote directly to the prototype. One nice feature is the inclusion of static member variables and static member functions.

While there is not much of a difference, it does allow us to write functions that cannot be accessed by the member functions (they can still be accessed, but it is a lot harder) and it can provide a good tool for grouping utility functions to that specific class. An example of static functions and variables is shown here:

class newItem {
static e() {
console.log(this);
}
static f = 10;
}

newItem1.e() //TypeError
newItem.e() //give us the class
newItem.f //10

The two static definitions were added to the newItem class and then we showcase what is available. With the function e and the static variable f, we can see that they are not included on the objects we create from newItem, but we have access to them when we access newItem directly. On top of this, we can see that the this that is inside the static function points to the class. Static members and variables are great for creating utility functions or even for creating the singleton pattern in JavaScript.

If we want to create the same experience in the old style, it would look like the following:

Item.e = function() {
console.log(this);
}
Item.f = 10;

As we can see, we have to put these definitions after the first definition of Item. This means that we have to be relatively careful in trying to group all of our code for the definition of our classes in the old style, whereas the class syntax allows us to put it all in a group.

On top of static variables and functions, we have the shorthand for writing the getters and setters for a variable in a class. This can be seen as follows:

get g() {
return this._g;
}
set g(val) {
if( typeof val !== 'string' ) {
return;
}
this._g = val;
}

With this getter and setter, we are able to do various things inside these functions when someone or something tries to access this variable. In the same vein that we set up a proxy to event on a change, we can do something similar with the getter and setter. We can also set up logging inside here. This syntax is quite nice when we want to access something as just a property name instead of writing our something like getG and setG.

Finally, there are the new private variables that have come in Chrome 76. While this is still in the candidate recommendation phase, it is still going to be discussed since it will most likely come into play. A lot of the time, we want to expose as much information as possible. However, there are times when we want to utilize internal variables to hold state or just not generally be accessed outside of our object. In this vein, the JavaScript community has come up with the _ solution. Anything that has an _ is considered a private variable. But, a user can still get access to these variables and manipulate them. Even worse than this, a malicious user could find a vulnerability in these private variables and be able to manipulate the system in their favor. One technique of creating private variables in the old system is something that looked like the following:

const Public = (function() {
let priv = 0;
const Private = function() {}
Private.prototype.add1 = function() {
priv += 1;
}
Private.prototype.getVal = function() {
return priv;
}
return Private;
})();

With this, no one has access to the priv variable except for the implementer. This gives us a public-facing system, without access to that private variable. However, there is still a catch with this system: if we create another Public object, we will still be affecting the same priv variable. There are other ways to make sure that we get new variables as we create new objects, but these are all workarounds to the system we are trying to make. Instead, we can now utilize the following syntax:

class Public {
#h = 10;
get h() {
return this.#h;
}
}

What that pound sign does is say that this is a private variable. If we try to get access to it from any one of our instances, it will come back undefined. This works great with the getter and setter interface as we will be able to control access to variables and even modify them if need be.

One final look into classes is the extend and super keywords. With extend, we are able to do just that with classes. Let's take our newItem class and extend its functionality. This could look like the following:

class extendedNewItem extends newItem {
constructor() {
super();
console.log(this.c());
}
get super_h() {
return super.h;
}
static e() {
super.e();
console.log('this came from our extended class');
}
}
const extended = new extendedNewItem();

We have a few interesting behaviors happening in this example. First, if we run Object.getPrototypeOf on our extended object, we will see that the prototype is what we would expect, extendedNewItem. Now, if we get the prototype of that, we will see that it is newItem. We have created a prototype chain just like many of the built-in objects.

Second, we have the capability of getting to our parent's methods from inside our class with the use of super. This is essentially a reference to our parent's prototype. We cannot chain these if we want to keep going through all of the prototypes. We would have to utilize something like Object.getPrototypeOf. We can also see, by inspecting our extended object, that we got all of the member variables that were held in our parent's system.

This gives us the ability to compose our classes together and create base classes or abstract classes that give us some defined behavior and then we can create extended classes that give us specific behavior that we want. We will see more code later on that utilizes classes and many of the concepts that we have gone over here, but remember that classes are just syntactical sugar for the prototype system and a good understanding of that will go a long way into understanding how JavaScript works as a language.

There are many great things about that class interface with the JavaScript ecosystem and there appear to be some other great ideas potentially coming in the future, such as decorators. It is always a good idea to keep an eye on the Mozilla Developer Network (MDN) page to see what is new and what is possibly coming out in the future. We will now take a look at modules and how they work in our system of writing clean and fast code.

A good rule of thumb is to not extend any class more than one, maybe two levels deep. If we go any further, we can start to create a maintenance nightmare, on top of potential objects getting heavy with information that they don't need. Thinking ahead will always be the best bet when we are creating our systems, and trying to minimize the impact of our classes is one way of reducing memory use.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.175.113