This page looks best with JavaScript enabled

Extending Class in Javascript

 ·   ·  ☕ 4 min read

Extend a class and create a sub class for easier maintainability. Sub class can make use of special super functions to extend the functionality of a class. Using sub classes you can build out a complex logic in steps rather than as one messy module.

See how to start with a Javascript class and class prototypes if you are new to Javascript classes.

Consider the example from our prototype discussion-

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
User.prototype.users = [];
class UserData {
  user = {
    name: "",
    type: "",
  };

  setUser({ name, type }) {
    this.user.name = name;
    this.user.type = type;
  }

  addUser() {
    this.users.push(this.user);
  }
}

UserData.prototype.users = [];

user1 = new UserData();
user1.setUser({ name: "Rama", type: "Teacher" });
user1.addUser();

console.log(user1.users); // [ { name: 'Rama', type: 'Teacher' } ]

user2 = new UserData();
user2.setUser({ name: "Kris", type: "Student" });
user2.addUser();

console.log(user2.users);
/* output
[
  { name: 'Rama', type: 'Teacher' },
  { name: 'Kris', type: 'Student' }
]
*/
console.log(user1.users); // // [ { name: 'Rama', type: 'Teacher' } ]
/* output
[
  { name: 'Rama', type: 'Teacher' },
  { name: 'Kris', type: 'Student' }
]
*/

Our application works beautifully and allows us to define users. But, what if we want to store information specific to teachers and students?

One option is to reuse the current variable to store all information.

1
2
3
4
5
6
7
8
user = {
  name: "",
  type: "",
  marks: "",
  grade: "",
  classes: [],
  subjects: [],
};

The mixing of data and business logic across types increases maintenance complexity.

  • Students do not have subjects and classes, but teacher does
  • Teachers do not have grades
  • What will happen if teachers need a different set of validation rules?

So, as good OOP students, we try to extend the UserData class.

1
2
3
4
5
6
7
8
class StudentData extends UserData {
  grade = "";
}

class TeacherData extends UserData {
  classes = [];
  subjects = [];
}

This segregates attributes, but we need to stitch them together with the parent. We will take the example of StudentData.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class StudentData extends UserData {
  grade = "";
  name = "";
  constructor(data) {
    super();
  }

  setUser(data) {
    super.setUser({
      name: data.name,
      type: "Student",
      grade: data.grade,
    });
  }
}

The super() function calls the parent constructor and sets the stage for extended class to access parent functions and/or values.

We then use a separate setUser method that overrides the parent method to set student-specific information. Potentially, we can also create student data validations here.

We now call the student class methods for creating student data instead of directly calling the user class methods.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
user2 = new StudentData();
user2.setUser({ name: "Kris", type: "Student", grade: 10 });
user2.addUser();

console.log(user2.users);
/* output
[
  { name: 'Kris', type: 'Student', grade: 10 }
]
*/

super can do many more things. We should also look at how extensions can have reusable functions and have better segregation of data for parents/extensions. However, this is a good start :)

Here’s the complete code if you want to run it in one go.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class UserData {
  user = {
    name: "",
    type: "",
    grade: "",
  };
  constructor() {}
  setUser({ name, type, grade }) {
    this.user.name = name;
    this.user.type = type;
    this.user.grade = grade;
  }

  addUser() {
    this.users.push(this.user);
  }
}

class StudentData extends UserData {
  grade = "";
  name = "";
  constructor(data) {
    super();
  }

  setUser(data) {
    super.setUser({
      name: data.name,
      type: "Student",
      grade: data.grade,
    });
  }
}

class TeacherData extends UserData {
  classes = [];
  subjects = [];
}

UserData.prototype.users = [];

user1 = new UserData();
user1.setUser({ name: "Rama", type: "Teacher" });
user1.addUser();

console.log(user1.users); // [ { name: 'Rama', type: 'Teacher', grade: undefined } ]

user2 = new StudentData();
user2.setUser({ name: "Kris", type: "Student", grade: 10 });
user2.addUser();

console.log(user2.users);
/* output
[
  { name: 'Rama', type: 'Teacher', grade: undefined },
  { name: 'Kris', type: 'Student', grade: 10 }
]
*/
console.log(user1.users); // // [ { name: 'Rama', type: 'Teacher' } ]
/* output
[
  { name: 'Rama', type: 'Teacher', grade: undefined },
  { name: 'Kris', type: 'Student', grade: 10 }
]
*/
Stay in touch!
Share on

Prashanth Krishnamurthy
WRITTEN BY
Prashanth Krishnamurthy
Technologist | Creator of Things