Namespacing Your JavaScript Objects
Problem
You want to encapsulate your data and functions in such a way as to prevent clashes
with other libraries.
Solution
Use an object literal, what I call a one-off object, to implement the JavaScript version of
namespacing. An example is the following
var jscbObject = { // return element getElem : function (identifier) { return document.getElementById(identifier); }, stripslashes : function(str) { return str.replace(/\\/g, ''); }, removeAngleBrackets: function(str) { return str.replace( /g,'>'); } }; var sample = " testing\changes "; var result = jscbObject.stripslashes(sample); result = jscbObject.removeAngleBrackets(result); console.log(result); //<div>testingchanges</div>
As mentioned elsewhere in this book, all built-in objects in JavaScript have a literal representation in addition to their more formal object representation. For instance, an Array can be created as follows:
var newArray = new Array('one','two','three');
or using the array literal notation:
var newArray = ['one','two','three'];
The same is true for objects. The notation for object literals is pairs of property names and associated values, separated by commas, and wrapped in curly brackets:
var newObj = { prop1 : "value", prop2 : function() { ... }, ... };
The property/value pairs are separated by colons. The properties can be scalar data values or they can be functions. The object members can then be accessed using the object dot-notation:
var tmp = newObj.prop2();
or:
var val = newObj.prop1 * 20;
or:
getElem("result").innerHTML=result;
Using an object literal, we can wrap all of our library’s functionality in such a way that the functions and variables we need aren’t individually in the global space. The only global object is the actual object literal, and if we use a name that incorporates functionality, group, purpose, author, and so on, in a unique manner, we effectively namespace the functionality, preventing name clashes with other libraries.
Advanced
I use the term one-off with the object literal rather than the more commonly known singleton because, technically, the object literal doesn’t fit the singleton pattern. A singleton pattern is one where only one instance of an object can be created. We can say this is true of our object literal, but there’s one big difference: a singleton can be instantiated at a specific time rather than exist as a static construct, which is what the solution defines.
var mySingleton = (function () { // Instance stores a reference to the Singleton var instance; function init() { // Singleton // Private methods and variables function privateMethod(){ console.log( "I am private" ); } var privateVariable = "Im also private"; var privateRandomNumber = Math.random(); return { // Public methods and variables publicMethod: function () { console.log( "The public can see me!" ); }, publicProperty: "I am also public", getRandomNumber: function() { return privateRandomNumber; } }; }; return { // Get the Singleton instance if one exists // or create one if it doesn't getInstance: function () { if ( !instance ) { instance = init(); } return instance; } }; })(); singleA = mySingleton.getInstance(); var singleB = mySingleton.getInstance(); console.log( singleA.getRandomNumber() === singleB.getRandomNumber() );
The singleton uses an Immediately-Invoked Function Expression (IIFE) to wrap the object, which immediately returns an instance of the object. But not just any instance —if an instance already exists, it’s returned rather than a new instance.
The latter is demonstrated by the object’s getRandomNumber() function, which returns a random number that is generated when the object is created, and returns the same random number regardless of which “instance” is accessed.
No comments:
Post a Comment