Section 1: Defined
The basic idea of OOP is that we use objects to model real world things that we want to represent inside our programs, and/or provide a simple way to access functionality that would otherwise be hard or impossible to make use of.
Objects can contain related data and code, which represent information about the thing you are trying to model, and functionality or behavior that you want it to have. Object data (and often, functions too) can be stored neatly (the official word is encapsulated) inside an object package (which can be given a specific name to refer to, which is sometimes called a namespace), making it easy to structure and access; objects are also commonly used as data stores that can be easily sent across the network.
from Object-oriented JavaScript for beginners
Objects are everywhere in JavaScript – almost every element is an Object whether it is a function,
array or string.
from Introduction to Object Oriented Programming in JavaScript
Object Oriented Programming is a programming language paradigm based on the concept that procedures and the data on which they operate can be viewed as two parts of the same thing – an object.
Object-oriented designs are better able to more accurately model the real world than procedural languages.
- Instead of viewing the world as a set of processes, it instead views the world as a collection of entities that are capable of certain behaviors.
- Furthermore, objected-oriented languages make it easier to create new data types to better represent real-world objects.
The fundamental idea behind object-oriented languages is to combine both data and the functions that operate on that data into a single unit called an object.
If implemented correctly:
- An object's functions, referred to as methods, provide the only way to access its data.
- In OO terminology, methods are also referred to as behaviors.
- In order to read or write a data item in an object, one of the object's methods must be called to access the data item and return or set its value.
- The data cannot be accessed directly.
- The data is hidden, and is safe from accidental alteration.
- Data and functions are said to be encapsulated into a single entity.
Both data encapsulation and data hiding are key concepts in the object-oriented paradigm.
The restriction that an object's data can only be changed by the object's methods ensures that nothing else can alter that data, and therefore simplifies writing, debugging, and maintaining the program.
Section 2: Concepts of the Object-Oriented Paradigm
Objects
An object is a computer representation of some real-world thing or event.
Example: if you own a Jeep, you might know several of its characteristics, such as the name of the model (Jeep Wrangler), the vehicle ID number (#51Y62BG826341Y), and the motor type (3.6-liter V-6).
Objects have both attributes (such as the model, VIN, and motor type) and behaviors (such as "lights go on" and "lights go off").
Classes
A class is a category of similar objects.
A class defines the set of shared attributes and behaviors found in each object in the class.
Objects are instances, or specific examples, of classes.
- Example: a group of objects representing automobiles might be formed into a class called "Automobile." Every automobile will have values for the attributes Make/Model, VIN, and Engine.
The data components of a class are called instance variables.
Classes must be defined by the programmer. When the program runs, objects can be created from the established class.
- The term instantiation is used when an object is created from a class.
- For example, a program could instantiate the Jeep Wrangler as an object from the class Automobile.
Just as an instance of a primitive type is called a variable, an instance of a class is called an object.
- There may be many objects of a class, just as there may be many variables of a primitive data type.
Placing data and functions together into a single entity is the central idea of object-oriented programming.

Section 3: Declaration
The ES2015/ES6 standard of JavaScript introduced the class syntax, providing a much more concise way of class declaration using a syntax that is similar to other object-oriented programming languages.
- However, what is known as a "class" is a call-able dynamic object (a constructor function) that can have properties and methods shared between all instances.
-
JavaScript actually uses prototypal inheritance, meaning that every object inherits properties and methods from its prototype object.
- The prototypal inheritance can emulate the classic class inheritance.
- Under the hood, JavaScript still considers classes a special type of function.
- The differences between declaring a class with or without the class syntax are explained in Class basic syntax - Not just a syntactic sugar.
- Bottom line: it is much simpler to define and reuse objects using the class syntax.
Class Declaration
In JavaScript, we declare the creation of a new class using the class
keyword (must be lowercase) followed by a capitalized class name and a pair of curly braces as shown:
class Student {
}
Class Attributes
Note that JavaScript does not require that the class declaration explicitly states which attributes/fields it has, although it is common to do.
Class attributes are simply listed in the class declaration:
class Student {
name;
studentID;
}
Class attributes (a.k.a. class fields or instance variables) are public by default, which violates OO expectations.
Private Class Attributes
ES2020 introduced private variables for classes, to protect class data from exposure beyond the class.
Attributes preceded by a hashtag (#
) are private variables.
A key feature of object-oriented programming is data hiding, which means that data is concealed within a class, so that it cannot be accessed mistakenly by functions outside the class.
The primary mechanism for hiding data is to put it in a class and make it private using the hashtag.
Variables or methods that are declared private are accessible only to members of the class.
class Student {
#name;
#studentID;
}
Constructor
constructor(param1, param2, ...)
is a special method in the body of a class.
- JavaScript automatically calls the
constructor()
method when you instantiate an object of the class. - The constructor should be used to initialize the properties, or attributes, of an instance.
- The constructor does not have to initialize every instance variable in the class unless that is desired, but the following examples tend to do so for completeness.
A constructor is vital to the class creation process because it initializes the state of an object (through its attributes) and it is called automatically when a new object is instantiated (defined and created).
- If you do not define a constructor for the class, a default no-argument constructor is created.
- The default constructor is an empty function, which does not modify the instance.
Another thing to note is that JavaScript enforces the constructor's name – has to be named constructor()
.
- Unlike other languages such as Java and C++, a JavaScript’s constructor does not use the class name to create a constructor.
- The keyword
this
and a dot must precede attribute names within the class body.
class Student {
#name;
#studentID;
constructor(sname, sID){
this.#name = sname;
this.#studentID = sID;
}
}
The this Keyword
When using this
inside of methods of an ES6 class, it points to the current object.
The this
keyword is used to refer to this instance within a class, once it is instantiated.
- You can find out more than you want to know about it in Javascript: Uncovering mysteries of ‘this’ keyword.
Accessor & Mutator Methods (Getters & Setters)
If implemented correctly, object-oriented programming limits access to data in a class by using a concept called data hiding.
-
However, there must be some way of accessing the object itself.
- Remember we stated earlier that "In order to read or write a data item in an object, one of the object's methods must be called to access the data item and return or set its value."
- Access to an object's attributes becomes possible when the programmer provides the object with public methods.
- Accessor (get) methods can be provided by the programmer to retrieve attributes from an object.
- Mutator (set) methods can be provided by the programmer to allow private (and hidden) class instance variables to be modified.
-
When access to private data members is restricted to the public methods, the designer controls how objects can be manipulated.
- For example, the designer may decide not to provide accessor and mutator methods for every data member.
- Further, mutator methods can (and should) include code to perform data validation, such as range checking, or may translate between the form of the data used in the interface and the form used in the implementation.
- The convention for naming getters and setters is that they should be prefixed with
get
orset
, followed by the attribute they're dealing with. - Instead of having to invoke a given method as a function, we can access it as a property of a given class.
Here is a tutorial on accessor and mutator methods.
Using get and set methods may seem essentially the same as declaring instance variables as public.
- However, if an instance variable is public, it may be read and altered (or corrupted) by any method in the program.
- On the other hand, if an instance variable is private, a public get method does allow other methods to read the data at will, but the get method can control the way that the data is formatted and displayed.
- A public set method can control attempts to modify the value of an instance variable so that any necessary conversions are made and the variable assumes only valid values.
- An excellent example of these concepts is a Date class, that may be implemented as three integer attributes for month, day, and year, or it could be implemented as a Julian data value. The user only perceives the date as a month, day, and year combination regardless of how it is implemented under the hood.
In addition, the designer can provide a get method for an instance variable but not a set method, thereby creating a read-only instance variable.
Here are some examples of accessor and mutator methods for the above class.
As explained, a getter method is one that returns a value, but lets us access it like we would a property.
In order to make a getter, we must make sure that our method:
- uses the
get
keyword - does not have any parameters
- has a
return
statement
// getter method
get name() {
return this.#name;
}
This next example of a getter method uses template literals which require backticks
- The backtick is on the upper left of most keyboards.
// getter method
get studentID() {
return `The student ID is ${this.#studentID}.`;
}
A setter method makes it possible to set class attributes, but instead of having to invoke a given method as a function, we can access it as a property of a given class.
In order to make a setter, we must make sure that our method:
- uses the
set
keyword - has a single parameter
set name(name) {
this.#name = name;
}
set studentID(ID) {
this.#studentID = ID;
}
Class Methods
You can also create methods to implement other class behaviors.
Class methods do not require the function
keyword.
The following examples show class information returned first using a template literal and second by concatenating a string:
studentInfo() {
return `${this.#studentID}: ${this.#name}`;
}
studentInfo2() {
return this.#studentID + ': ' + this.#name;
}
Demo
This is a link to a demo program testing the above code.
- Please view page source to see the underlying code.
class Student {
#name;
#studentID;
constructor(sname, sID){
this.#name = sname;
this.#studentID = sID;
}
// getter method
get name() {
return this.#name;
}
// getter method
get studentID() {
return `The student ID is ${this.#studentID}.`;
}
set name(name) {
this.#name = name;
}
set studentID(ID) {
this.#studentID = ID;
}
set studentID(ID) {
this.#studentID = ID;
}
studentInfo2() {
return this.#studentID + ': ' + this.#name;
}
}
The following figure provides an infographic on the JavaScript class declaration.

Instantiating an object and invoking its behaviors will be explained in the next section.
Section 4: Instantiation
The term instantiation is used when an object is created from a class.
- For example, a program could instantiate Ima Student as an object from the class
StudentClass
.
Just as an instance of a primitive type is called a variable, an instance of a class is called an object.
- There may be many objects of a class, just as there may be many variables of a primitive data type.
To instantiate an object in JavaScript, use let
or const
, along with the keyword new
.
This first example creates a new instance of the StudentClass
and calls the no-argument constructor supplied by JavaScript.
let studentInstance1 = new StudentClass();
If you want to initialize the object's attributes, you can call the setter methods:
studentInstance1.name = "Heidi Clare";
studentInstance1.studentID = "000763728";
Notice again that calls to setter methods do not require parentheses or arguments in parentheses.
In the second example, a new instance, or object, of the StudentClass
is created and the declared constructor
is invoked to initialize the class attributes.
let studentInstance2 = new StudentClass("Wally Ballou", "123456789");
Note that even if the class attributes have been initialized, they can be changed by invoking the mutator method.
One of the preceding examples demonstrated calling a setter method, and the following shows a getter invocation.
alert(studentInstance2.name);
alert(studentInstance2.studentID);
Here is an example of a function to test the above code. It is called from the onload
event like <body onload="test();">
function test() {
let studentInstance1 = new StudentClass();
studentInstance1.name = "Heidi Clare";
studentInstance1.studentID = "000763728";
alert(studentInstance1.studentInfo2());
const studentInstance2 = new StudentClass("Ty Coon", "123456789");
alert(studentInstance2.name);
studentInstance2.name='Reid Enright';
alert(studentInstance2.name);
alert(studentInstance2.studentID);
alert(studentInstance2.studentInfo());
}
Section 5: Abstraction
An object-oriented programming language is generally characterized by four core features – abstraction, polymorphism, inheritance, and encapsulation.
(JavaScript supports all of these features in some fashion.)
from Introduction to Objects (CS 2282)
So the four principle concepts upon which object-oriented design and programming rest are Abstraction, Polymorphism, Inheritance and Encapsulation (easily remembered as A-PIE). These notes introduce and explain these four concepts.
While A-PIE may be easy to remember, the principles build upon one another in the following order: Abstraction, Encapsulation, Inheritance and Polymorphism.
Abstraction Defined
Abstraction, as a process, denotes the extraction of the essential details about an item, or a group of items, while ignoring the inessential details, while abstraction, as an entity, denotes a model, a view, or some other focused representation for an actual item.
- In both cases, the objective is to reduce the complexity apparent to the abstraction's user.
Data abstraction can be implemented in OO languages through the creation of classes, which represent abstract data types (ADTs).
- ADTs capture both data representation and the operations that are allowed on that data.
Abstraction can also be viewed as taking an idea, concept, or object and expressing it in terms of the constructs provided by the programming language.
- Using abstraction, a person might be represented as a bundle of variables and methods, e.g. Name, Height, Weight, HairColor, eat( foodItem ), sleep(), run() etc.
Object-oriented languages allow programmers to define a higher-level abstraction tailored to the problem at hand.
- The program can be adapted to the problem by defining new types of objects and relationships specific to that problem, rather than being forced to use existing, language-provided data types that might not best model the problem.
Scenario
In order to process something from the real world, we have to extract the essential characteristics of that object. Consider the following example.

Data abstraction can be viewed as the process of refining away the unimportant details of an object, so that only the useful characteristics that define it remain. Evidently, this is task specific.
- Depending on how a car is viewed (for example, in terms of something to be registered, or alternatively something to be repaired, etc.) different sets of characteristics will emerge as being important.
Formulated as such, abstraction is a very simple concept and one that is integral to all types of computer programming, object-oriented or not.
Functional Abstraction
The process of modeling functionality suffers from the same pitfalls and dangers as found when abstracting the defining characteristics, that is, unnecessary functionality may be extracted, or alternatively, an important piece of functionality may be omitted.
- The programmer goes about determining which functionality is important in much the same way as they determine which data items are important.
Section 6: Encapsulation
Encapsulation, is one step beyond abstraction because it extends the idea of abstraction by modeling and linking the functionality of that entity.
- Encapsulation deals with the issue of how to best modularize the features of a system into classes, which in turn are modularized into methods and attributes.
- While abstraction involves reducing a real world entity to its essential defining characteristics, encapsulation extends this idea by also modeling and linking the functionality of that entity.
- In effect, encapsulation is an approach through which abstraction is accomplished, just as modular design is another approach.
- In OO design, encapsulation is the approach through which abstraction is accomplished.
As a principle, encapsulation ensures that you are not required to know how something is implemented in order to be able to use it.
The implication of encapsulation is that you can build anything any way you want, and if the implementation is later changed it will not affect other components within the system, provided that the interface to that component does not change.
Encapsulation Defined
Encapsulation is the act of grouping into a single object both data and the operations that affect that data.
Encapsulation links the data to the operations that can be performed upon the data, and hence ensures that data is only used in an appropriate manner.
- In effect, encapsulation places a boundary around an object's properties and methods.
In object-oriented programming, encapsulation is the inclusion within a program object of all the resources needed for the object to function – basically, related data and the methods that manipulate those data.
- The collective term for data items and methods bundled together with access restrictions is a class.
- Each class is a new data type.
Classes are useful for the following reasons:
- Classes can be used to model real world entities, thereby permitting object-oriented languages to model a wide range of problems.
- Bundling data and functionality together produces self-contained units that are more maintainable, reusable, and deployable.
-
By enforcing the idea of encapsulation, object-oriented languages make it more
difficult for the programmer to produce 'bad' code.
- Encapsulation allows an object-oriented language to enforce the integrity of a type (that is, to make sure data is used in an appropriate manner) by preventing programmers from accessing data in a non-intended manner (for example, asking if an Integer is true or false, etc.).
- Through encapsulation, only a predetermined group of functions can access the data.
Consider a Student
class.
- An object, for example
testStudent
, is an instance of the classStudent
. - Within the object there are instance variables such as name, studentID, major, and GPA.
- When a method operates on an object it may change the instance variables for that object.
- If the changeMajor method is called for the object
testStudent
, then the instance variable major that belongs totestStudent
would be altered accordingly.
Encapsulation is intended to provide a "cover" or "coating" that hides the internal structure of the class from the environment outside.
- Other classes (and end users) are prevented from doing anything to the insides of the class.
- They cannot change the data or alter any procedures in a method.
- Only the methods of the class can change its data, so no unexpected changes can be imposed on the class from the outside.
Information Hiding
Encapsulation alone does not prevent the data of an object from being manipulated by functions other than the methods bound to the class.
- Encapsulation is merely the grouping of attributes and methods in a single structure.
- Clearly, encapsulation is not enough – data must be protected in such a way that only the object itself can make such changes through its own behavior.
- Protecting data from manipulation by entities outside the object can be achieved by requiring that access to data be restricted to the services of the object that contains the data.
- Therefore, realization of encapsulation requires information hiding.
Information hiding is the technique of concealing implementation details within the objects themselves, while the interface remains visible.
Information hiding requires the visibility of data to be restricted to within the (encapsulated) module.
- Data is concealed within a class, so that it cannot be accessed mistakenly by functions outside the class.
- Access to data within an object is restricted to only those methods defined by the object's class.
- An object must be directed to change its own data with a message, because outside processes are prohibited from altering the nature of the object.
Information hiding is accomplished through the use of the #
(private) access
modifier and the use of accessor and mutator methods designed to carefully control access to
private data.
If instance variables are not declared as private, they are encapsulated but not hidden. Encapsulation without information hiding is inadequate.
Section 7: Inheritance
The third of our four core OO features, inheritance, is the process of creating new classes, called derived classes, from existing or base classes.
- It is a form of software reusability in which new classes are created from existing classes by absorbing their attributes and behaviors and embellishing those with capabilities the new classes require.
- The derived class inherits all the capabilities of the base class but can add enhancements.
- The base class is unchanged by this process.
- All classes derived from a superclass inherit the capabilities of that superclass.
- Subclasses are then customized beyond the capabilities inherited from the superclass.
- Inherited members are not shown in subclass declarations, but inherited members are nevertheless present in the subclasses.
Inheritance is one of the most powerful features of object-oriented programming.
The figure below shows a base class called Student
, along with two derived classes called
Undergrad
and Grad
.
- All types of students share common features and behaviors, which are modeled in
Student
. - The derived classes,
Undergrad
andGrad
, inherit all of those features and add new attributes and behaviors that differentiate them from each other.

For the sake of brevity (and laziness), the sample code used to test the features of inheritance used the more simple inheritance structure shown below:

Recall the StudentClass
class that we defined in an earlier section:
class StudentClass {
#name;
#studentID;
constructor(sname, sID){
this.#name = sname;
this.#studentID = sID;
}
// getter method
get name() {
return this.#name;
}
// getter method
get studentID() {
return `The student ID is ${this.#studentID}.`;
}
// getter method
get ID() {
return `The student ID is ${this.#studentID}.`;
}
set name(name) {
this.#name = name;
}
set studentID(ID){
this.#studentID = ID;
}
set studentID(ID){
this.#studentID = ID;
}
studentInfo() {
return `${this.#studentID}: ${this.#name}`;
}
studentInfo2() {
return this.#studentID + ': ' + this.#name;
}
}
To create a class that inherits from another, we use the extends
keyword.
class GradstudentClass extends StudentClass {
#undergradSchool; // instance variable new to this derived class
constructor(name, ID, undergradSchool){
super(name, ID); // call to inherited constructor
this.#undergradSchool = undergradSchool;
}
}
The keyword extends
is used to indicate that we want to inherit
from the parent class StudentClass
.
The constructor of the derived class first calls the constructor from the base class to initialize the attributes inherited from the base class, and then initializes any attributes added by the derived class.
- The method
super()
is used in the derived class to invoke the inherited constructor from the base class.
Setter and Getter methods
Setter and getter methods can be added for any attributes declared in the derived class.
If setter and getter methods were provided for attributes in the base class, they do not have to be provided again in the derived class since they are inherited.
Setter and getter methods may be provided for any attributes added by the derived class.
Other Methods
Additional methods can be defined as needed, to complement those inherited from the base class.
Here are some guidelines to remember when writing methods in a derived class:
- An attribute declared in the derived class can only be accessed by prefacing it with
this
keyword. - A private attribute inherited from a base class can only be accessed via its setter or getter methods (if any).
- Setter and getter methods are inherited from the base class, but can only be accessed
by prefacing the method name with
super
- The
super
keyword is not needed to access public attributes in a base class, but correct OO design tries to use only private attributes.
Here is the inheritance demo. Please view the page source or see the code below to see what can and cannot be done in a derived class. The page source includes comments that explain what is happening.
class GradstudentClass extends StudentClass {
#undergradSchool;
constructor(name, ID, undergradSchool){
super(name, ID);
this.#undergradSchool = undergradSchool;
}
set undergradSchool(school) {
this.#undergradSchool = school;
}
get undergradSchool() {
return this.#undergradSchool;
}
gradstudentDetails() {
return super.name + " (" + super.ID + ") graduated from " + this.#undergradSchool +".";
}
gradstudentInfo() {
return this.studentInfo() + " graduated from " + this.#undergradSchool +".";
}
}
Method Overriding
In many situations we have base class methods that might need to be modified in the derived class.
A derived class can redefine a base class method using the same signature, that is, methods of a derived class can have the same name as those in the base class.
A method's signature refers to the number, data type, parameter type, and order of the arguments in the parameter list.
Method overriding: When the same method name and signature exists in both the base class and the derived class, when that method is called in the derived class the method defined in the derived class will be executed, that is, the derived class method overrides the base class method.
By default, all methods specified in the base class are inherited in the derived class, so the
GradstudentClass
inherits all methods declared in the StudentClass
,
including studentInfo()
, which returns all info about the student.
- However,
GradstudentClass
includes an additional attribute,undergradSchool
, not inherited fromStudentClass
. - The inherited method
studentInfo()
does not reportundergradSchool
. - We can specify a new method in
GradstudentClass
, also namedstudentInfo()
, which returns details about all of the attributes in both the base class and the derived class, and ifstudentInfo()
is called by an object of typeGradstudentClass
then the new version will be used instead of the inherited version.studentInfo() {
return super.studentInfo() + " is a graduate of " + this.#undergradSchool + ".";
}
Why is an esoteric subject like overriding being explored? Because it is essential to polymorphism.
Inheritance References
Here are some useful links that discuss inheritance:
Section 8: Polymorphism
Polymorphism refers to methods that can have multiple forms.
- Definition: the ability of a language to have duplicate method names in an inheritance hierarchy (overriding) and to apply the method that is appropriate for the object to which the method is applied (dynamic binding).
The term binding, or method lookup, refers to the act of selecting which method will
be executed in response to a particular invocation.
Dynamic binding refers to binding that is performed at run time.
In case of dynamic binding, we do not have to know the exact type of an object.
It is enough to be sure that instance will be of some type or has a superclass
that contains needed functionality. In such cases the exact behavior is determined
at run-time. That important ability simplifies code in cases where many objects have
the same interface with different implementations.
Polymorphism allows a number of different classes of objects to respond to the same request by providing subclasses with methods with the same name and signature as a method in the superclass.
- Through the use of polymorphism, one method call can cause different actions to occur depending on the type of the object receiving the call.
With polymorphism, the programmer can deal in generalities and let the execution-time environment concern itself with the specifics.
- The programmer can command a wide variety of objects to behave in manners appropriate to those objects without even knowing the types of those objects.
- Thus, it is possible to write code that manipulates objects of many different classes in a uniform and consistent manner without regard for their exact type, that is, we can write programs in a general fashion to handle a wide variety of existing and yet-to-be-specified related classes.
Polymorphism promotes extensibility.
- Software can be written independently of the types of the objects to which method calls are sent.
- Thus, new types of objects that can respond to existing messages can be added into such a system without modifying the base system.
- With polymorphism, it is possible to design and implement systems that are more easily extensible.
Example
- Suppose a set of bird classes such as
Penguin
,Kiwi
,Hummingbird
, etc., are all derived from superclassBird
. - In object-oriented programming, each of these classes might be endowed with the
ability to
move()
. - Although each class has its own
move()
method, themove()
method for each bird is quite different. - When causing a bird to
move()
, whatever the bird may be, it would be nice to be able to treat all of the birds generically as objects of the superclassBird
. - Then to make any bird move, we could simply call method
move()
of superclassBird
and let the program determine dynamically (that is, at execution time) which subclassmove()
method to use. - To enable this kind of behavior, we declare
move()
in the superclass, and then we overridemove()
in each of the subclasses to make the bird move. - In the subclass
Hummingbird
, themove()
method would cause the object of typeHummingbird
to fly. - In the subclass
Kiwi
, themove()
method would cause the object of typeKiwi
to run. - In the subclass
Penguin
, themove()
method would cause the object of typePenguin
to swim. - Each movement, however, is initiated by a call to the
move()
method associated with the superclassBird
, and the proper movement is determined dynamically, depending on the type of object being moved. - To test this behavior, we declare an array that holds an object of type
Penguin
, an object of typeKiwi
, and an object of typeHummingbird
. (Remember, section 3 of the array notes noted "You can store anything in a JavaScript array; the data does not even have to be the same type.") - Then we direct each array item to move, and the
Penguin
object swims, theHummingbird
object flies, and theKiwi
object runs.
Here is a polymorphism demo. You can view the page source or see the code below to see how polymorphism is implemented.
// Bird class - the base class
class Bird {
#type;
#color;
#locale;
#diet;
move() {
return "The bird is flying.";
}
makesNoise() {
return "The bird is making noise.";
}
eat() {
return "The bird is eating.";
}
}
// derived class Penguin - overrides move method to swim
class Penguin extends Bird {
#height;
#territory;
move() {
return "The penguin is swimming!";
}
dive() {
return "The penguin is diving!";
}
}
// derived class Kiwi - overrides move method to run
class Kiwi extends Bird {
#endangered;
#predator;
#subspecies;
move() {
return "The kiwi is running!";
}
dig() {
return "The kiwi is digging a nest.";
}
}
// derived class Hummingbird - does not override move method because hummingbirds fly
class Hummingbird extends Bird {
#size;
#weight;
migrate() {
return "The hummingbird is going south.";
}
hover() {
return "The hummer is hovering.";
}
}
function test() {
let pBird = new Penguin();
alert(pBird.move());
alert(pBird.dive());
// Create array of birds
let birdList = [new Penguin(), new Hummingbird(), new Kiwi()];
alert(birdList[0].move());
alert(birdList[1].move());
alert(birdList[2].move());
}
Here is another polymorphism demo focusing on savings and checking accounts. Again, please view the page source to see how polymorphism is implemented or click on the example page.
Here is another discussion of How JavaScript works: 3 types of polymorphism with an example.
Note that we have demonstrated that the four core features of object-oriented programming – abstraction, polymorphism, inheritance, and encapsulation – are supported by JavaScript.
Section 9: Alternate Approaches
You can define objects in several other ways in JavaScript.
It is common to see an object defined using an object literal, as follows:
var testStudentObj1 = { name: "Barry Cade", studentID: "112233445" };
Here are some additional examples.

Reflecting on the above figure, using the ES6-based approach to implementing objects in JavaScript may help to make the concepts more familiar to students.
- However, if you take the back-end development class, you may be expected to be familiar with the older prototype-based approach, especially object literals.
Further, you must keep in mind that the new Class simply offers a more familiar syntax on prototypal classes, and under the hood, ES6 Classes are still based on prototypal inheritance.
Here is the 4430 professor's material explaining prototype based objects, or you can view his PowerPoint presentation below.
Section 10: Final Thoughts
One benefit of the object-oriented approach is the close correspondence between the real-world things being modeled by the program and the objects in the program.
This makes it easy to conceptualize a programming problem. You figure out what parts of the problem can be most usefully represented as objects, and then put all the data and methods connected with that object into the class specification.
In some situations it may not be obvious what parts of a real-life situation should be made into objects because there are no hard and fast rules. Often you proceed by trial and error. You break the problem into objects in one way and write trial class specifiers for these objects. If the classes seem to match reality in a useful way, you continue. If they don't, you start over, selecting different entities to be classes. The more experience you have with OOP, the easier it will be to break a programming problem into classes.
Some of the benefits of object-oriented programming are probably not apparent at this point because OOP was devised to cope with the complexity of large programs. Smaller programs have less need for the organizational power that OOP provides. The larger the program, the greater the benefit.
Section 11: References Used for Notes
- Guide to Understanding Classes in JavaScript
- Classes in JavaScript
- The bleeding edge of JavaScript classes
- Learn How to Create Classes in JavaScript ES6 Tutorial: JavaScript Class
- Class basic syntax
- JavaScript ES6 Class Syntax
- JavaScript Objects: Create, Access, Object Constructor, Properties & Methods
- Define Class & Instantiation with Javascript ES6
- Classes in JavaScript
- Property getters and setters
- Javascript: Constructors, Methods, Properties, and Accessors in Class and Objects
- Javascript Accessors & Mutators (Getters & Setters) Tutorial
- Classes
- Private class features
- constructor
- JavaScript Classes
- JavaScript Object Accessors
You may notice that the preceding notes consist of bits and pieces of all of these sites.