A key concept in object-oriented programming is information hiding. It refers to the practice of declaring some parts of a class public
, and others private
, depending on what we want clients of the class to be able to see and do. It protects the application from programmers who may decide to use a class in ways which are contrary to the original intentions of the class’s author.
Unlike object-oriented languages such as Java and C#, the JavaScript syntax does not include keywords such as ‘public
’ and ‘private
’ (access modifiers) which would allow programmers to practice information hiding quickly and easily. However many programmers, myself included, are used to designing applications based on object-oriented programming, so we need a way to simulate this concept using the features available in the JavaScript language.
There are essentially two ways to do this: using constructor functions, and using the module pattern.
Constructor Functions
I touched on constructor functions in my last post. These are basically functions which are intended to be called with the ‘new
’ keyword. By calling a function in this way, we create an object based on the function, with its own state, and where any occurrence of the ‘this
’ prefix inside the function will create a public
property or function on the created object.
This feature of JavaScript was added to appeal to programmers coming from an object-oriented background, where the ‘new
’ keyword is a fundamental feature.
Notice in the example below how the name of the function is capitalized – this is conventional when declaring constructor functions to remind us to treat it as such and to call it with the ‘new
’ keyword.
function Rectangle()
{
var height;
var width;
this.getArea = function(){
return height*width;
};
this.setWidth = function(w){
width = w;
};
this.setHeight = function(h){
height = h;
};
this.shapeType = 'rectangle';
}
var rect = new Rectangle();
rect.setWidth(4);
rect.setHeight(3);
alert(rect.getArea());
alert(rect.shapeType);
alert(rect.height);
var rect2 = new Rectangle();
rect2.setWidth(10);
rect2.setHeight(2);
alert(rect2.getArea());
alert(rect2.shapeType);
alert(rect2.height);
Constructor functions also allow us to modify all instances, including ones which have already been created, by updating the function’s prototype property, as shown below.
var rect = new Rectangle();
Rectangle.prototype.numberOfCorners = 4;
alert(rect.numberOfCorners);
The Module Pattern
The module pattern essentially describes the practice of writing a function which returns an object literal. The function represents our object-oriented class. Any client of this ‘class
’ has access only to the object literal returned by the function. Therefore, members defined as part of this object literal are effectively public
. Any members declared inside of the function are private
, however, they are accessible from the object literal thanks to the concept of closures in JavaScript.
We can see how this works in code in this example.
function getRectangleInstance()
{
var height;
var width;
return {
getArea: function(){
return height*width;
},
setWidth: function(w){
width = w;
},
setHeight: function(h){
height = h;
},
shapeType: 'rectangle'
};
}
var rect = getRectangleInstance();
rect.setWidth(4);
rect.setHeight(3);
alert(rect.getArea());
alert(rect.shapeType);
alert(rect.height);
var rect2 = getRectangleInstance();
rect2.setWidth(10);
rect2.setHeight(2);
alert(rect2.getArea());
alert(rect2.shapeType);
alert(rect2.height);
This variation of the module pattern (there are many), allows us to easily create multiple instances of a class, each of which has its own state.
Which One to Use?
The question of whether to use constructor functions or the module pattern to enforce information hiding in JavaScript is largely a personal choice. In JavaScript – The Good Parts, Douglas Crockford seems to identify constructor functions as a ‘bad part’ of JavaScript, his reasoning being that forgetting to use the ‘new
’ keyword when calling a constructor function can lead to unexpected behaviour. However, constructor functions do allow us to easily modify all instances of a class by modifying the function’s prototype property.
Personally, I don’t really see a problem with using constructor functions. Or rather, I don’t see the possibility of forgetting to use ‘new
’ as enough of a reason to avoid using them. Just try not to forget! Constructor functions are a powerful feature and they arguably make for more readable code, particularly to those coming from an object-oriented background, not to mention the added advantage of emulating inheritance by accessing the function’s prototype.
As the name suggests, I see the module pattern as being more useful to emulate modules, rather than classes which act as templates for multiple instances. By using the module pattern to define an immediately invoked function expression, we can create a module which is not intended to be instantiated multiple times, but which encapsulates a set of functionality and avoids littering the global namespace. In the example below, we implement the module pattern in this way, declaring an immediately invoked function to assign an object to the shapeModule
variable. This object, or module, can contain its own private
members, and exposes the getRectangleInstance
function, along with any other desired public
members. However, by immediately invoking the shapeModule
function, we lose the ability to create multiple instances of it. Therefore this variation of the module pattern is often described as emulating the concept of a namespace, rather than a class, in Java or C#.
var shapeModule = function(){
var privateField = 'someValue';
return {
getRectangleInstance: function(){
var height;
var width;
return {
getArea: function(){
return height*width;
},
setWidth: function(w){
width = w;
},
setHeight: function(h){
height = h;
},
shapeType: 'rectangle'
};
},
getCircleInstance: function(){
}
};
}();
var rect = shapeModule.getRectangleInstance();
alert(rect.shapeType);
The important message here is that it is possible, and desirable, to implement information hiding in JavaScript, and once you know how it is not too difficult to do so.
The post Information Hiding in JavaScript appeared first on The Proactive Programmer.