Over a million developers have joined DZone.
Refcard #174

Object-Oriented JavaScript

Advanced Techniques for Serious Web Applications

Written by

Covers advanced object-oriented techniques in JavaScript, including object creation, member scoping, namespaces, inheritance and modularization.

Free PDF
Section 1


As HTML5 standards mature, JavaScript has become the de-facto programming language of the web for client-side environments, and is gaining ground rapidly on the server-side. As JavaScript code-bases grow larger and more complex, the object-oriented capabilities of the language become increasingly crucial. Although JavaScript's object-oriented capabilities are not as powerful as those of static server-side languages like Java, its current object-oriented model can be utilized to write better code.

In this Refcard, you'll learn how to write object-oriented code in JavaScript. Code samples include some EcmaScript 5 (JavaScript's specification) features and have been tested in Firefox 17, Chrome 23 and Internet Explorer 9.

Section 2

Comparison of Java and JavaScript

Java JavaScript
Statically typed Dynamically typed
Custom types are defined with class, interface or enum Custom types are defined with functions and prototypes
Types cannot be changed at runtime Types can be changed at runtime
Variables needs a type when declared (Strong typing) No type needed when variables are declared (Loose typing)
Constructors are special methods Constructor is just a function;  no distinction between function and constructor
Class and instance are different entities Everything is object; constructor functions and prototypes are also object
Static and instance members supported No direct static member support
Abstract types supported with abstract classes and interfaces No direct abstract type support
Good enough member scoping options; private, package, protected, public Only public members supported by language
Rich inheritance mechanism Poor prototypal inheritance
Method overloading and overriding possible No direct overloading and overriding support
Rich reflection features Some reflection features
Modularity with package support No direct package or module support
Section 3

Object Type Definition

Type Definition

Every function is also a type, and new instances of these functions can be created with the "new" operator. Function declaration can behave like a constructor, and in this case is called a Constructor Function. In constructor functions, prototype methods and fields can be accessed.

function MyType(){
   if (!(this instanceof MyType))
        throw new Error("Constructor can't be called as a function");
var myInstance = new MyType();
MyType(); // Error: Constructor can't be called as a function

In Eclipse, object types can be easily inspected in the JavaScript perspective. Constructor, instance members, static members and inner functions are all separated in Outline View.

Inspecting Object Types

Instance Members

Instance members are accessed from instance objects which are created with the "new" operator. Instance members are created via "this" keyword, prototype, constructor closure or Object.defineProperty method.

function Cat(name){
        var voice = "Meow";
        this.name = name;
        this.say = function(){
                return voice;
Cat.prototype.eat = function(){
        return "Eating";
var cat = new Cat("Fluffy");
Object.defineProperty(cat, "numLegs",{value: 4,writable:true,enumerable:true,configurable:true});

console.log(cat.name); // Fluffy
console.log(cat.numLegs); // 4
console.log(cat.say()); // Meow
console.log(cat.eat()); // Eating

Static Members

There is no direct support for static members. Constructor functions are used to create static members. Static members can't be accessed with "this" keyword.

Public Static Members:

function Factory(){

// public static method
Factory.getType = function (){
return "Object Factory";
// public static field
Factory.versionId = "F2.0";

Factory.prototype.test = function(){
console.log(this.versionId); // undefined
console.log(Factory.versionId); // F2.0
console.log(Factory.getType()); // Object Factory

var factory = new Factory();

Private Static Members:

var Book = (function () {
        // private static field
        var numOfBooks = 0;

        // private static method
        function checkIsbn(isbn) {
                if (isbn.length != 10 && isbn.length != 13) 
                        throw new Error("isbn is not valid!");

        function Book(isbn, title) {
                this.isbn = isbn;
                this.title = title;
                this.getNumOfBooks = function () {
                        return numOfBooks;

        return Book;

var firstBook = new Book("0-943396-04-2", "First Title");
console.log(firstBook.title); // First Title
console.log(firstBook.getNumOfBooks()); // 1
var secondBook = new Book("0-85131-041-9", "Second Title");
console.log(firstBook.title); // First Title
console.log(secondBook.title); // Second Title
console.log(firstBook.getNumOfBooks()); // 2
console.log(secondBook.getNumOfBooks()); // 2

Abstract Types

JavaScript is a loosely typed language, so you don't have to specify the variable type of a variable when you declare it and pass as an argument. This reduces the need for abstract types like interfaces. But abstract types may be needed to collect common functionality when inheritance is used.


var abstractCreateLock = false;
// abstract type
function BaseForm(){
                throw new Error("Can't instantiate BaseForm!");
BaseForm.prototype = {};
BaseForm.prototype.post = function(){
        throw new Error("Not implemented!");

function GridForm(){

GridForm.prototype = new BaseForm();
abstractCreateLock = true;
GridForm.prototype.post = function(){
        // ...
        return "Grid is posted.";

window.BaseForm = BaseForm;
window.GridForm = GridForm;


var myGrid = new GridForm();
console.log(myGrid.post()); // Grid is posted.
var myForm = new BaseForm(); // Error: Can't instantiate BaseForm!


There is no direct interface or virtual class support in JavaScript. It can be mimicked as below, leaving a method signature check:

var Interface = function (name, methods) {
        this.name = name;
        // copies array
        this.methods = methods.slice(0);

Interface.checkImplements = function (obj, interfaceObj) {
        for (var i = 0; i < interfaceObj.methods.length; i++) {
                var method = interfaceObj.methods[i];
                if (!obj[method] || typeof obj[method] !== "function")
                        throw new Error("Interface not implemented! Interface: " + interfaceObj.name + " Method: " + method);
var iMaterial = new Interface("IMaterial", ["getName", "getPrice"]);

function Product(name,price,type){ 
        Interface.checkImplements(this, iMaterial);
        this.name = name;
        this.price = price;
        this.type = type;

Product.prototype.getName = function(){
        return this.name;

Product.prototype.getPrice = function(){
        return this.price;

var firstCar = new Product("Super Car X11",20000,"Car");
console.log(firstCar.getName()); // Super Car X11
delete Product.prototype.getPrice;
var secondCar = new Product("Super Car X12",30000,"Car"); // Error: Interface not implemented! Interface: IMaterial Method: getPrice

Singleton Objects

var Logger = {
        log: function(logText){
                if(console && console.log)


function Logger(){
Logger.enabled = true;
Logger.log = function(logText){
        if(console && console.log)

Logger.log("test"); // test
Logger.enabled = false; 
Logger.log("test"); //
Section 4

Object Creation

With "new" Operator

Instances of built-in or user-defined object types can be created with the "new" operator. The "new" operator runs only with constructor functions. An already created object can't be used with "new" again. First, the "new" operator creates an empty object; then it calls the constructor function while assigning the newly created object as "this". The constructor function runs with the given arguments, performing its coded initializations.

//or var dog = {};
//or var dog = new MyDogType();
var dog = new Object();
dog.field1 = "Scooby";
dog.owner = {};
dog.owner.name = "Mike";
dog.bark = function(){
        return "Woof";

console.log(dog.field1); // Scooby
console.log(dog.owner.name); // Mike 
console.log(dog.bark()); // Woof

With Object Literal

It is very easy to create objects with object literal. It is also possible to create nested objects.

var dog = {
                return "Woof";

console.log(dog.name); // Scooby
console.log(dog.owner.name); // Mike 
console.log(dog.bark()); // Woof
Section 5

Member Scoping

Private Fields

In JavaScript, there is no built-in private field support. But this support can be achieved with constructor closures. Variables defined within a constructor function can be used as private fields. Any methods using private fields should be declared in the constructor function (note that prototype methods can't be declared in the constructor function and used with private fields). Private setter and getter functions should be declared in the constructor function.

function Customer(){
        // private field
        var risk = 0;

        this.getRisk = function(){
                return risk;
        this.setRisk = function(newRisk){
                risk = newRisk;
        this.checkRisk = function(){
                if(risk > 1000)
                        return "Risk Warning";
                return "No Risk";

Customer.prototype.addOrder = function(orderAmount){
        this.setRisk(orderAmount + this.getRisk());
        return this.getRisk();

var customer = new Customer();

console.log(customer.getRisk()); // 0
console.log(customer.addOrder(2000)); // 2000
console.log(customer.checkRisk()); // Risk Warning

Private Methods

Also called "Nested" or "Inner Functions". Private methods are defined within another function and can't be accessed from outside. Private methods can be declared in any part of a function.

function Customer(name){
        var that = this;
        var risk = 0;
        this.name = name;
        this.type = findType();
        // private method
        function findType() {
                return "GOLD";


function Customer(name){
        var that = this;
        var risk = 0; 
        this.name = name;
        // private method
        var findType = function() {
                return "GOLD";
        this.type = findType();

var customer = new Customer("ABC Customer"); // ABC Customer
                                       // 0
console.log(customer.type); // GOLD
console.log(customer.risk); // undefined

If a private inner function is returned outside, its methods can be called from outside:

function Outer(){
        return new Inner();

        //private inner
        function Inner(){
                this.sayHello = function(){

(new Outer()).sayHello(); // Hello

Privileged Methods

Prototype methods can't access private fields; everything attached to them is also "public". We need a way to declare methods so that (a) they are accessible publicly and (b) they can access private members, which means privileged or protected access. For this purpose, the following code can be used:

function Customer(orderAmount){
        // private field
        var cost = orderAmount / 2;
        this.orderAmount = orderAmount;
        var that = this;

        // privileged method
        this.calculateProfit = function(){
                return that.orderAmount - cost; 

Customer.prototype.report = function(){

var customer = new Customer(3000);
customer.report(); // 1500

Public Fields

For public fields, prototype or instance can be used. Prototype fields and methods are shared by new instances. (Prototype objects are also shared). If a new instance changes the field or method in its object, the change is not reflected in other instances. To change all instances, we need to change it in the prototype object.

function Customer(name,orderAmount){
        // public fields
        this.name = name;
        this.orderAmount = orderAmount;
Customer.prototype.type = "NORMAL";

Customer.prototype.report = function(){

Customer.prototype.promoteType = function(){
        this.type = "SILVER";

var customer1 = new Customer("Customer 1",10);
// public field
customer1.country = "A Country";
customer1.report(); // Customer 1
                    // 10
                    // NORMAL
                    // A Country

var customer2 = new Customer("Customer 2",20);
console.log(customer2.type); // SILVER
console.log(customer1.type); // NORMAL

Public Methods
Prototype methods are public. Any methods attached to "this" are also public.
function Customer(){
        // public method
        this.shipOrder = function(shipAmount){
                return shipAmount;
// public method
Customer.prototype.addOrder = function (orderAmount) {
        var totalOrder = 0;
        for(var i = 0; i < arguments.length; i++) {
                totalOrder += arguments[i];
        return totalOrder;

var customer = new Customer();
// public method
customer.findType = function(){
        return "NORMAL";
console.log(customer.addOrder(25,75)); // 100
console.log(customer.shipOrder(50)); // 50
console.log(customer.findType()); // NORMAL
Section 6


There are different ways to implement inheritance in JavaScript. "Prototypal Inheritance" – using prototype as an inheritance mechanism – has many advantages. For example:

function Parent(){
        var parentPrivate = "parent private data";
        var that = this;
        this.parentMethodForPrivate = function(){
                return parentPrivate;
Parent.prototype = {
        parentData: "parent data",
        parentMethod: function(arg){
                return "parent method"; 
        overrideMethod: function(arg){
                return arg + " overriden parent method"; 

function Child(){
// super constructor is not called, we have to invoke it
        var that = this;
        this.parentPrivate = function(){
                return that.parentMethodForPrivate();

Child.prototype = new Parent();// parent
Child.prototype.constructor = Child;

//lets add extented functions
Child.prototype.extensionMethod = function(){
        return "child's " + this.parentData;

//override inherited functions
Child.prototype.overrideMethod = function(){
        //parent's method is called
        return "Invoking from child" + Parent.prototype.overrideMethod.call(this, " test");

var child = new Child();// parent
                // parent data 
                // child
console.log(child.extensionMethod()); //child's parent data
console.log(child.parentData); //parent data
console.log(child.parentMethod()); //parent method
console.log(child.overrideMethod()); //Invoking from child test overriden parent method
console.log(child.parentPrivate()); // parent private data

console.log(child instanceof Parent); //true
console.log(child instanceof Child); //true

When a member of child object is accessed, it is searched from the object's members. If it is not found there, then it is searched in its prototype object. If it is not found there, then it is searched in the parent object's members and prototype. It is searched up to the Object's prototype. This hierarchy is also called the "Prototype chain". The following diagram illustrates the chain:


Section 7


Once we have many custom object types, we need to group them and manage their visibility, dependencies, and loading. "Namespace and Module Pattern" can be used to handle these tasks. (Note that EcmaScript version 6 (Harmony) is beginning to develop a full-fledged module system. Until it is implemented by browsers, there are some useful libraries to facilitate these features.)


There is no direct namespace support in JavaScript. We can create namespace via objects and fill our object types in object properties:

//create namespace
var myLib = {};
myLib.myPackage = {};

//Register types to namespace
myLib.myPackage.MyType1 = MyType1;
myLib.myPackage.MyType2 = MyType2;


Modules are a way of dividing our JavaScript code-base into packages. Modules export some object type definitions and import other modules. The module system loads each module and its dependencies. First it runs the dependencies in appropriate order; then the module code is executed. Some libraries can be used for this purpose.

In modules, we define new types, import some types from other modules and export our public types. Here is an example of a module definition:

Module.define("module1.js",["dependent_module1.js","dependent_module2.js",...], function(dependentMod1, dependentMod2) { //IMPORTS

function ExportedType1(){
        // use of dependent module's types
        var dependentType = new dependentMod1.DependentType1();
function ExportedType2(){

return { ExportedType1: ExportedType1, ExportedType2: ExportedType2,...};


To use a module (can work asynchronously or synchronously):

Module.use(["module1.js"], function(aModule){
        console.log("Loaded aModule!");
        var AType = aModule.AnExportedType;
        var atype1Instance = new AType();
Section 8

Custom Exceptions

In JavaScript, there are built-in exceptions like Error, TypeError and SyntaxError which may be created and thrown during runtime. Every exception is "unchecked". An ordinary object can be used as an exception with throw statement. Thus, we can create our own custom exceptions and throw and catch them. It is good practice to write exceptions that extend JavaScript's standard Error object.

function BaseException() {
BaseException.prototype = new Error();
BaseException.prototype.constructor = BaseException;

BaseException.prototype.toString = function(){
        // note that name and message are properties of Error
        return this.name + ": " + this.message;

function NegativeNumberException(value) {
        this.name = "NegativeNumberException";
        this.message = "Negative number! Value: " + value;
NegativeNumberException.prototype = new BaseException();
NegativeNumberException.prototype.constructor = NegativeNumberException;

function EmptyInputException() {
        this.name = "EmptyInputException";
        this.message = "Empty input!";
EmptyInputException.prototype = new BaseException();
EmptyInputException.prototype.constructor = EmptyInputException;

var InputValidator = (function(){

var InputValidator = {};
InputValidator.validate = function(data){
        var validations = [validateNotNegative,validateNotEmpty];
        for(var i = 0; i < validations.length; i++){
                try {
                catch (e) {
                        if (e instanceof NegativeNumberException) {
                                throw e;
                        else if (e instanceof EmptyInputException) {
                                // tolerate it
                                data = "0";
return InputValidator;

function validateNotNegative(data){
                if (data < 0)
                        throw new NegativeNumberException(data);
function validateNotEmpty(data){
                if (data == "" || data.trim() == "")
                        throw new EmptyInputException();


        console.log(e.toString()); // NegativeNumberException: Negative number! Value: -1
        console.log("Validation is done."); // Validation is done.
Section 9

Custom Events

Custom events reduce code complexity and decrease coupling of objects. Here is a typical event pattern:

function EventManager(){
var listeners = {};

EventManager.fireEvent = function(eventName, eventProperties) {
        if (!listeners[eventName]) 

        for (var i = 0; i < listeners[eventName].length; i++) {

EventManager.addListener = function(eventName, callback) {
        if (!listeners[eventName]) 
                listeners[eventName] = [];

EventManager.removeListener = function(eventName, callback) {
        if (!listeners[eventName]) 
        for (var i = 0; i < listeners[eventName].length; i++) {
                if (listeners[eventName][i] == callback) {
                        delete listeners[eventName][i];

EventManager.addListener("popupSelected", function(props){
        console.log("Invoked popupSelected event: " + props.itemID);

EventManager.fireEvent("popupSelected", {itemID:"100"}); // Invoked popupSelected event: 100
Section 10

Writing Components

JavaScript lets developers add new behaviors to HTML elements. These enrichments can be combined in a component structure. There is a continuing specification work by the W3C on "Web Components". Here is a commonly used pattern to bind JavaScript objects to DOM objects. In this way, we can collect behaviors and manage their lifecycles.

1- Define JavaScript Component:

function InputTextNumberComponent(domElement){

InputTextNumberComponent.prototype.initialize = function(domElement){
        domElement.onchange = function(){
                //just a format
                domElement.value = "-" + domElement.value + "-";
domElement.jsComponent = this; //Expando property
        this.domElement = domElement;

InputTextNumberComponent.prototype.resetValue = function(){
        this.domElement.value = "";

2- Define CSS Class to Correlate HTML Elements with JavaScript Components:

<style type="text/css">
.inputTextNumber { text-align:right; }

HTML element should be as follows:

<input type="text" class="inputTxtNumber" name="NumberField" size="10" value="Click me!" onClick="this.jsComponent.resetValue()">

3- When page is loaded (or DOM ready), detect HTML elements and create components:

window.onload = function(){
        var inputTextNumbers = document.getElementsByClassName("inputTextNumber");
        for(var i = 0; i < inputTextNumbers.length; i++){
                var myComp = new InputTextNumberComponent(inputTextNumbers.item(i));


  • Featured
  • Latest
  • Popular
Getting Started With Docker
Teaches you typical Docker workflows, building images, creating Dockerfiles, and includes helpful commands to easily automate infrastructure and contain your distributed application.
10.3k 7,449
Getting Started With Real User Monitoring
Teaches you how to use new web standards—like W3C’s Beacon API—to see how your site is performing for actual users, letting you better understand how to improve overall user experience.
4,492 3,749
Core Java
Gives you an overview of key aspects of the Java language and references on the core library, commonly used tools, and new Java 8 features.
104.2k 264.3k
JavaFX 8
Gives you what you need to start using the powerful JavaFX 8 UI and graphics tool with code snippets and visual examples of shapes and controls.
6,829 9,071
Continuous Delivery With Jenkins Workflow
Provides an introduction to the Jenkins Workflow plugin, a tool that extends the popular CD application to manage even the most complex software pipelines and help you continuously deliver more efficiently.
8,722 9,902
Functional Programming in JavaScript
Explains functions, data types, and techniques to demonstrate the functional paradigm through the familiar JavaScript language.
12k 8,797
Java Caching
Explores the building blocks of JCache and other caching APIs, as well as multiple strategies for implementing temporary data storage in your application.
10.5k 10.7k
Getting Started With Microservices
Still re-deploying your entire application for one small update? Microservices deploy modular updates and increase the speed of application deployments.
13.8k 14.3k
Getting Started With MQTT
Explores the fundamentals of MQTT, including message types, QoS levels, and security.
6,098 7,234
Monitoring NGINX
Overcome dropped connections, server errors, and more by efficiently monitoring your NGINX web server.
4,889 3,862
Getting Started With Apache Tomcat
Learn Apache Tomcat, a pure Java open-source web server that implements the Java Servlet, JavaServer Pages, and Expression Language specifications.
8,896 7,380
IntelliJ IDEA Essentials
Helps Java developers navigate the various facets of this world-class IDE, with tips, tricks, shortcuts, and quick tutorials on editor basics, navigation, and more.
20.4k 91.1k
{{ card.title }}
{{card.downloads | formatCount }} {{card.views | formatCount }}

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}