JavaScript Classes

Introduction Classes Inheritance Getters and Setters Protect Class Properties Static Methods JavaScript Source Summary

Introduction

This page covers JavaScript class implementation, inheritance, getters, setters, how to define dynamic read-only properties and static methods. JavaScript classes are templates for JavaScript objects. Classes are part of ES6.

You must declare a class before using the class. Hoisting isn't available with JavaScript classes. This page loads an external JavaScript file in the header, named Cats.js.

<script async src="javascript/Cats.js"></script>

Classes

The following two, blue and red, boxes demonstrate use of a JavaScript class. Below the boxes, I posted the class implementation and box HTML markup. The markup demonstrates creating a new class with constructor parameters.

Each class displays some information about specific cats and calls the Javascript operator typeof, with this as the operand. As you can see a JavaScript class is considered type object.

Click for Cat Info
Click for Cat Info

Class Implementation

Every class has a constructor which is called when a new class is created. The name of the constructor is always constructor(). Include constructor parameters that you want applied when a new object of the class is created.

The Cat constructor requires two strings. Formal arguments are breed and behavior.

class Cat {
 /**
 * Cat constructor.
 * @param breed: string
 * @param behavior: string.
 * @return: a new Cat object.
 */
 constructor(breed, behavior) {
  this.breed = breed;
  this.behavior = behavior;
  this.element = null;
 }
 
 /**
 * Compose a string with 
 * the cat's breed and behavior.
 * @return string: cat's breed, behavior.
 */
 showInfo() { 
  let s = this.breed+','+this.behavior; 
  return s.toString();
 }
 
 /**
 * Compose a string with the typeof operator.
 * @return string: this type.
 */
 showType() { 
  let s = '<br />Type: ' + typeof this; 
  return s.toString();
 } 
 
 /**
 * Show everything about this
 * cat in an HTML element.
 * @param string: ID of an HTML element.
 */ 
 showInfoType(sId){
  this.element = document.getElementById(sId);
  this.element.innerHTML = this.showInfo();
  this.element.innerHTML += this.showType();
 }
}

Box HTML Markup

The markup for each clickable box displays below. Create a new Cat. Pass parameters to the constructor each time code creates a new Cat.

Call method showInfoType(). The only parameter is the value of the box's id.

Create a new class with, new, the name of the class, and any constructor parameters. For example, below you'll see, c = new Cat('Siamese', Loud'), where Siamese is the constructor's first parameter and Loud is the constructor's second parameter.

<div 
id="bBlue" 
class="box" 
onclick="var c = new Cat('Siamese','Loud'); c.showInfoType('bBlue');" 
style="background-color:blue;"
>
Click for Cat Info
</div>

<div 
id="bRed" 
class="box" 
onclick="var c = new Cat('Bombay','Fat'); c.showInfoType('bRed');" 
style="background-color:red;"
>
Click for Cat Info
</div>

Inheritance

Inheritance helps us reuse the Cat class constructor, methods and properties, in a subclass called CatWild. Reusing code offers the ability to write concise, legible script.

Let's implement CatWild as a subclass of Cat. I declared Cat and CatWild in the same file. See Cats.js.

Tap a Wild Cat Button to see the results. Read Inheritance Code with comments below, for implementation details.

Click for Wild Cat Info
Click for Wild Cat Info

Inheritance Code

Notice CatWild extends the Cat class. Class CatWild's constructor calls Cat's constructor with the keyword super(...).

Class CatWild reuses class Cat's showInfoType() method, within CatWild's showInfoTypeRegion() method. In other words, CatWild.showInfoTypeRegion() calls Cat.showInfoType() because they are the same object. Therefore showInfoType() from Cat is a method of the CatWild class too.

The CatWild constructor extends the Cat base, or Cat parent class. Therefore CatWild's constructor also includes the breed and behavior. Then CatWild's constructor calls super(breed, behavior). The call to super(breed, behavior) calls the parent class, Cat's constructor.

// CatWild inherits from Cat:
class CatWild extends Cat {

/**
* Constructor calls Cat
* constructor, with Cat
* parameters.
* The last parameter
* is assigned to
* CatWild property; region.

* @param breed: string cat breed.
* @param behavior: string cat behavior.
* @param region: string cat territory.
*/
constructor(breed, behavior, region) {
// Call parent, Cat,
// class constructor.
super(breed, behavior);
this.region = region;
}

/**
* Display every field.
* @param sId: String id of 
* HTML element.
*/
showInfoTypeRegion(sId) {
// The parent 'Cat' class
// includes public methods
// and elements. 
// You can access them in this
// child class.
this.showInfoType(sId);
this.element.innerHTML += '
Region: '+this.region; } }

Wild Cat Box Markup

The HTML markup is essentially the same as the Cat box markup, except create a new CatWild object, with a third constructor parameter. Also call method showInfoTypeRegion() instead of showInfoType().

var c = new CatWild('Jaguar','Fast','South America'); c.showInfoTypeRegion('bG');

Getters and Setters

You can add getters and setters to any class. Getters and setters allow developers to retrieve and assign property values, through a type of method.

Advantages

Getter and setter methods allow developers to modify access to some properties. Use of setter methods allow developers to perform validation on values before assignment.

Read Only

Exclusion of setter methods on a class indicates the developer may not want assignment of a value to a property. However, at this time, developers can look at the code and assign a value directly to the property, as you'll see below.

CatHybrid Child Class

Here we'll add getters and setters to the CatHybrid class which extends the Cat class. Hybrids either mix wild cats with domesticated cats or different breeds of domesticated cats. The breeder often tries to cultivate a cat that looks wild yet behaves like a domesticated variety.

The CatHybrid constructor will extend just the Cat base, or parent class. Therefore its constructor also includes the breed and behavior.

class CatHybrid extends Cat{...}

Extension

Note that CatHybrid could extend CatWild instead of Cat. Then the CatHybrid constructor would call the CatWild's constructor with super(...), and every CatWild required parameter. Additionally every property and method along the chain from Cat > CatWild > CatHybrid would be available to CatHybrid.

Instead we'll create a simple constructor that can pass along Cat constructor parameters, breed, behavior. We added one new parameter named, wildtype.

constructor(breed, behavior, wildtype){...}

Simple CatHybrid Display

The light aqua box creates a default new CatHybrid and gives it a few unique qualities.

The red box creates a new CatHybrid, provides some unique qualities, then creates the read only property called personality. Property personality was preassigned the value Awesome.

Tap a hybrid cat button.

Click for Hybrid Cat Info
Click Create Read Only Personality

Cat Hybrid Box Markup

The markup is similar to the original Box HTML Markup, except create a new CatHybrid(). Assign a value to the setter. For example, see the Savannah cat's qualities:

c.qualities='16 Inches Tall from the Shoulder';

Call method showInfoTypeHybrid().

No Setter Method

This little example demonstrates two attempts to assign a value to a property which has a getter method but not a setter method.

The blue box tries to use the non-existent getter method for oddity, to assign the value Wild Appearance. It doesn't succeed.

The pink box circumvents the setter and simply assigns the value Wild Appearance to the property catOddity. Property catOddity really has nothing to protect it from invalid assignments.

Developers can use the setter method to suggest future developers use setter, rather than assigning values directly to a property. Setter use currently isn't enforced.

Developers can omit the getter method to suggest future developers avoid assigning values to a specific property. However, there currently may not exist a technique to avoid assignment of predeclared properties. Yet, as you'll see below, dynamically defined properties provide a level of protection.

Click: Attempt Assign Get Only Oddity=Wild Appearance
Click: Workaround Assign Get Only Oddity=Wild Appearance

Box Markup with Workaround

The blue box attempts to assign Wild Appearance to the non existent getter property. So it doesn't work.

c.oddity='Wild Appearance';

The pink box assigns Wild Appearance directly to the Cat object's property catOddity and it does work.

c.catOddity='Wild Appearance';

The entire markup follows.

<div 
id="bB" 
class="box"
style="background-color:blue;"
onclick="var c = new CatHybrid('Ocicat','Spotted','Domestic Cat with Ocelot Appearance'); c.qualities='Spotted fur.'; c.oddity='Wild Appearance'; c.showInfoTypeHybrid('bB'); " 
title="Hybrid Cat Button"
>
Click: Attempt Assign Get Only <em>Oddity=Wild Appearance</em>
</div>

<div 
id="bY" 
class="box" 
onclick="var c = new CatHybrid('Oriental Shorthair','Siamese without Points','Domestic Siamese'); c.qualities='Foreign Appearance'; c.catOddity='Wild Appearance';  c.showInfoTypeHybrid('bY');" 
style="background-color:#ffaaaa; color:black;"
title="Hybrid Cat Button"
>
Click: Workaround Assign Get Only <em>Oddity=Wild Appearance</em>
</div>

Protect Class Properties

The pink box below, creates a read-only property named personality then attempts to assign Playful to replace personality's default value of, Awesome. The assignment doesn't succeed.

The aqua box creates a writeable property named personality then attempts to assign Playful to replace personality's default value of, Awesome. The assignment does succeed.

Protect Properties

From this example you can see that creating readable and writable properties dynamically works to protect class variables.

Getters and setters, in this version of JavaScript, could be considered developer suggestions for clean code, yet they're easy to work around. Use defineProperty to create read only properties, as you'll see below.

Click Create: Read Only, Attempt Assign Personality = Playful
Click Create: Writeable, Attempt Assign Personality = Playful

Read Only or Writeable Properties

Create read only or write only properties, in a class, with the defineProperty method. Pass this as the first parameter, the name of your property, in this case; personality, as your second parameter. Provide a value, and writeable: false for read only properties. Apply writeable: true for read and write properties, as follows.

assignReadOnly(){
Object.defineProperty(this, "personality", {
value: " Awesome",
writable: false
});
}

assignWriteable(){
Object.defineProperty(this, "personality", {
value: " Awesome",
writable: true
});
}

Cat Hybrid Class

See the entire CatHybrid class with getter and setter methods, plus methods to create dynamic read only or writable properties.

Both CatHybrid and CatWild derive from class Cat. They extend class Cat, which allows each sub class to access properties and methods in the super class, Cat.

// CatHybrid's parent
// class is Cat.
class CatHybrid extends Cat{

/**
* CatHybrid constructor.

* @param breed: string cat breed.
* @param behavior: string cat behavior.
* @param wildtype: string wild cat base.
*/
class CatHybrid extends Cat{
	
constructor(breed, behavior, wildtype) {
// Call parent, Cat,
// class constructor.
super(breed, behavior);
this.wildtype = wildtype;
}

get qualities() {
return this.catQualities;
}

set qualities(d) {
this.catQualities = d;
}

// You can get
// but cannot set
// oddity.
get oddity() {
return this.catOddity;
}
	
assignReadOnly(){
Object.defineProperty(this, "personality", {
 value: " Awesome",
 writable: false
});
}

assignWriteable(){
Object.defineProperty(this, "personality", {
value: " Awesome",
writable: true
});
}

showInfoTypeHybrid(sId) {
this.showInfoType(sId);
this.element.innerHTML += '
Wild Cat: '+this.wildtype; if(this.oddity != null){ this.element.innerHTML += '
Oddity:'+this.oddity; } else{ this.element.innerHTML +="
Oddity was not assigned."; } if(this.personality != null){ this.element.innerHTML += '
Personality:'+this.personality; } else{ this.element.innerHTML +="
Personality was not assigned."; } if (this.catQualities != null){ this.element.innerHTML +='
Qualities: '+this.catQualities; } } static description() { let s = "A hybrid cat is a domestic feline crossbred with a wild cat." return s + " TypeOf: " + typeof CatHybrid; } }

Static Methods

Static methods allow developers to call a method, with the name of the class, rather than the name of the class object. That means you can not access any class object properties, unless those properties are passed through the static method's parameter list.

Add Static Method

Add a static method to the CatHybrid class, as you can see above. That method named, definition() will always return the same information.

/**
* Static method
* prepend the method name 
* with the static keyword
*
*/
static description() {
let s = "A hybrid cat is a domestic feline crossbred with a wild cat." 
return s + " TypeOf: " + typeof CatHybrid;
}

Call a Static Method

The CatHybrid typeof operator returns function. Previously calling typeof on a new class object, returns object.

Click for Hybrid Cat Description.

Static Method Markup

Notice you call CatHybrid.description() not c = new CatHybrid(..); c.description();. Call the class name, not the class object.

<div 
class="box" 
onclick="this.innerHTML = CatHybrid.description()" 
style="background-color:#0088ff;"
>
Click for Hybrid Cat Description.
</div>

Entire JavaScript

You may see the entire JavaScript source code applied to this lesson at Cats.js. I added fewer comments to the source code, to minimize download time. I added more comments to this page, to clarify each feature.

Summary

This page covered JavaScript class implementation, inheritance, getters, setters, how to define dynamic read-only properties and static methods. JavaScript classes are templates for JavaScript objects. Classes are part of ES6.