Encapsulation in JavaScript

Some Notes from a discussion of encapsulation in JavaScript

The topic of encapsulation in JavaScript came up in our bi-weekly technologists group recently. First question was, what is encapsulation and why is it a good thing. The first obvious benefit is the elimination of global values.

An example with global variables. TAX_RATE is vulnerable; it is a global variable that can be overwritten.

// Not Best Practice. Relies on Global variables and functions.
var TAX_RATE = 0.07;

function calculateTotalPrice(basePrice) {
    return basePrice + (basePrice * TAX_RATE);
}

function calcPrice () {
    var basePrice = document.getElementById('ex1_basePrice').value;
    basePrice = basePrice - 0; // cast to integer
    var totalPrice = calculateTotalPrice(basePrice);
    document.getElementById('ex1_totalPrice').value = totalPrice;
}

The problem with the global variable, or course, is that anything can come along a modify it. In this HTML example, click Calculate Price. Then open a console window (Use Firebug or Developer Tools) and alter this global variable:

> TAX_RATE = 1.00;

Now click Calculate Price. It would be just as easy to overwrite the global functions to produce different values:

> calcPrice = function() { return 1; }

Now our price calculation is completely re-written.

One practice to prevent the collision of global variables is to organize them in a single global variable:

var myApp = {
    TAX_RATE: 0.08,
     
    calculateTotalPrice: function(basePrice) {
        return basePrice + (basePrice * this.TAX_RATE);
    },
     
    calcPrice: function() {
        var basePrice = document.getElementById('ex3_basePrice').value;
        basePrice = basePrice - 0;
        var totalPrice = myApp.calculateTotalPrice(basePrice);
        document.getElementById('ex3_totalPrice').value = totalPrice;
    }
};

This works, but it can still leave myApp vulnerable. myApp.TAX_RATE is still globally accessible.

Using encapsulation, it is possible to create protected members.

var calcPrice2 = (function() {
    // private 
    var PRIVATE_TAX_RATE = 0.05;
     
    function calculateTotalPrice2(basePrice) {
        return basePrice + (basePrice * PRIVATE_TAX_RATE);
    }
     
    // public
    return function() {
        var basePrice = document.getElementById('ex2_basePrice').value;
        basePrice = basePrice - 0;
        var totalPrice = calculateTotalPrice2(basePrice);
        document.getElementById('ex2_totalPrice').value = totalPrice;               
    };
})();

Leave a Reply

Your email address will not be published. Required fields are marked *