Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

JavaScript Objects in 15 Minutes

4.54/5 (16 votes)
27 Nov 2013CPOL4 min read 28.8K   235  
How to deal with objects creation in JavaScript, encapsulation and inheritance, different techniques, and examples

Introduction

This article is a brief guide on how to create objects in different ways, implement inheritance and encapsulation, use the prototype property, and test my code by using the unit test framework for JavaScript QUnit (http://qunitjs.com/).

Background

Factory Pattern: The factory method pattern is an object-oriented creational design pattern to implement the concept of factories and deals with the problem of creating objects (products) without specifying the exact class of object that will be created. - From Wikipedia.

Basically, it is a specific way to create new object instances by using a method.

Everything is a Object

In JavaScript, everything is an object, keep it present always.

JavaScript is a very flexible language which could be an advantage or a disadvantage, if you are a ordered developer then you will be fine. You can create objects but the relationship between them and object-oriented programming is not direct. For example, there is no class keyword in JavaScript, but you can simulate similar functionality and OO concepts like encapsulation and inheritance.

JavaScript is called a prototype-based, object-oriented programming language, so you will use prototypes to create or clone objects before using them.

QUnit

I will use Qunit to create test methods and assert values:

Download QUnit .js and .css files from http://qunitjs.com. Add both to your project. Read getting started section. We will use the equal function which basically compares two values and evaluates them as a Boolean condition.

Object Literal Pattern

The easiest way to create an object, just need name, curly braces and specify the properties and/or methods you need:

JavaScript
var person = {
    name: 'steve',
    age: 25,
    getInfo: function () {
        return this.name + ' ' + this.age;
    }
};

Here, I created a person object with two properties; name as string and age as number; also, a function with name getInfo that returns a string with the value of both properties.

Test Method

On this test method, I use the person object already created and invoke its getInfo() function.

JavaScript
test("Object literal test", function () {
    expect(1);

    var expected = 'steve 25';

    var actual = person.getInfo();

    equal(actual, expected, actual);
});

After running the page, the result is:

Image 1

This indicates that the 'Object Literal Test' test passed without errors.

Factory Pattern

Every object in JavaScript has a prototype object which can be used to clone an object by using the new keyword.

JavaScript
function getEmployee(name, department) {
    var newEmployee = new Object();
    newEmployee.name = name;
    newEmployee.department = department;
    newEmployee.getInfo = function () {
        return this.name + ' ' + this.department;
    }
    return newEmployee;
};

First, I need to create a function which allows the factory pattern implementation, receiving by parameters the values of the properties I need to set, inside the function use the New Object() instruction to create an empty object, finally just specify the properties and methods needed.

Test Method

In this test, I create two object instances named employee1 and employee2, both with a name and department.

JavaScript
test("Factory Pattern test", function () {
    expect(2);
    var employee1 = getEmployee('David', 'financial');
    var employee2 = getEmployee('Mark', 'sales');

    equal(employee1.getInfo(), 'David financial', employee1.getInfo());
    equal(employee2.getInfo(), 'Mark sales', employee2.getInfo());
});

Result:

Image 2

Class Simulation

As I said, there is no class keyword in JavaScript; instead, we can simulate it using a function and a default constructor.

JavaScript
function Computer(brand, is64, color) {
    var _brand = brand;
    var _is64 = is64;
    var _color = color;
    this.getInfo = function () {
        return _brand + ' ' + is64 + ' ' + _color;
    }
};

Here, I created a function that works as a default constructor and at the same time, allows me to implement encapsulation. Using the var keyword to declare each property (or variable) ensures that they cannot be modified by external code.

Test Method

Just create two objects of type computer and assign their internal values by using the default constructor.

JavaScript
test("Class simulation", function () {
    expect(2);
    var toshiba = new Computer('toshiba', true, 'black');
    var hp = new Computer('hp', false, 'red');

    equal(toshiba.getInfo(), 'toshiba true black', toshiba.getInfo());
    equal(hp.getInfo(), 'hp false red', hp.getInfo());
});

Result:

Image 3

Prototype Property

Everything is an object in JavaScript, and everything has a prototype property which is an object itself that contains properties and methods that should be available to all instances of the type you are working with.

For this example, we will rewrite the getInfo method for the Computer class using its prototype property. I will name it Computer2 class.

JavaScript
function Computer2(brand, is64, color) {
    this.brand = brand;
    this.is64 = is64;
    this.color = color;
};
Computer2.prototype.getInfo = function () {
    return this.brand + ' ' + this.is64 + ' ' + this.color;
};

The difference is on getInfo implementation, it is made outside the definition of the class and using the prototype property so I’m affecting all the instances of the computer2 object that use the function getInfo.

Test Method

JavaScript
test("Instance test using prototype, overwrite original function shared across all instances", 
      function () {
    expect(2);
    var toshiba = new Computer2('toshiba', true, 'black');
    var hp = new Computer2('hp', false, 'red');
    //overwrite the original implementation
    Computer2.prototype.getInfo = function () {
        return this.brand + ' is ' + this.is64 + ' and of color ' + this.color;
    };
    equal(toshiba.getInfo(), 'toshiba is true and of color black', toshiba.getInfo());
    equal(hp.getInfo(), 'hp is false and of color red', hp.getInfo());
});

After creating the two instances of Computer2, I overwrite the getInfo function with a new implementation which basically changes the return text. The interesting point here is that I’m changing the implementation for all the instances, for created ones and the new ones.

Result:

Image 4

Inheritance

To implement inheritance in JavaScript, we have to use something called IIFE (an immediately-invoked function expression (or IIFE, pronounced "iffy") is a JavaScript design pattern which produces a lexical scope using JavaScript's function scoping, - Wikipedia.org), basically, a block of code that is invoked immediately after the browser loads.

So let’s create three classes, a superclass and two subclasses, as follows:

Image 5

Next is my superclass called USER, it has two properties and a method:

JavaScript
//superclass
var User = (function () {
    function User(name, isActive) {
        this.name = name;
        this.isActive = isActive;
    }
    User.prototype.getInfo = function () {
        return this.name + ' is active: ' + this.isActive;
    }
    return User;
})();

Next is the subclass Developer, there are several important parts:

In the inline function used to create the object, I receive parent, which represents the superclass I’m inheriting. Use the prototype property to change the object type to User. Use parent.call to make a reference to the parent function (constructor) and send this to be assigned as a child. Write the new methods as needed, for example: Writecode(). At the end of the IIFE declaration, specify the parent class between parentheses, like this: (user).

JavaScript
var Developer = (function (parent) {
    Developer.prototype = new User();
    //intheritance is accomplished by changing the prototyp object for the child

    Developer.prototype.constructor = Developer;
    function Developer(name, isActive, languajes) {
        this.languajes = languajes;
        parent.call(this, name, isActive);
    }
    Developer.prototype.WriteCode = function () {
        return 'writing code!';
    };
    return Developer;
})(User);

var Dba = (function (parent) {
    Dba.prototype = new User();
    //intheritance is accomplished by changing the prototyp object for the child

    Dba.prototype.constructor = Dba;
    function Dba(name, isActive, isSqlDba, isOracleDba) {
        this.IsSqlDba = isSqlDba;
        this.IsOracleDba = isOracleDba;
        parent.call(this, name, isActive);
    }
    Dba.prototype.MakeBackup = function () {
        return 'backup done!';
    };
    return Dba;
})(User); 

Test Method

Basically, create two different child objects instances; invoke the parent method (getInfo) as well as the children's new methods (WriteCode and MakeBackup):

JavaScript
test("Inheritance Test", function () {
    expect(4);
    var dev = new Developer('James', true, ' vb.net and c#');
    var dba = new Dba('John', true, true, false);
    
    equal(dev.getInfo(), 'James is active: true');
    equal(dba.getInfo(), 'John is active: true');
        
    equal(dev.WriteCode(), 'writing code!', dev.WriteCode());
    equal(dba.MakeBackup(), 'backup done!', dba.MakeBackup());
});

Image 6

Using the Code

Check the link below for a Visual Studio 2013 solution with all the code I used inside the article. Uncomment specific tests to see the results:

History

  • Version 1: 26/11/2013

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)