Singleton through object literal versus module pattern, code organization pros&cons - javascript

Which one do you prefer and what are pros & cons one over another ?.
Personally i found singleton hard to read and maintain, a lot of context changes(this), always ends with caching right context through var self = this (or some proxy like $.proxy) + i will always have one global variable(singleton), while in second approach i can avoid creating global variable if module doesn't need to expose any API.
Simple example: (User click on "add to cart", some ajax get triggered and on success html(notification) is created)
Html
<div class="cart">
Add to cart
</div>
Module pattern
Not truly module pattern by definition, because i'm not returning anything from it, click handler can access outer scope via closure.
;(function(window, $, undefined) {
function constructHtml(data) {...}
function addToCart(product_id, quantity) {
...
$.ajax({
...
success: function(data) { constructHtml(data); }
});
}
$(function() {
var $addBtn = $('div.cart a');
var productId = $addBtn.data('product-id');
$addBtn.click(function(e) {
e.preventDefault();
addToCart(productId);
});
});
})(this, jQuery);
Singleton - Object literal(same example)
var Cart = {
settings: {
$addBtn: $('div.cart a'),
productId: $('div.cart a').data('product-id')
},
init: function() {
this.bindUiActions();
},
bindUiActions: function() {
var self = this;
this.settings.$addBtn.click(function(e) {
e.preventDefault();
self.addToCart(self.settings.productId);
});
},
addToCart: function(product_id, quantity) {
...
var self = this;
$.ajax({
...
success: function(data) {
self.constructHtml(data);
}
});
},
constructHtml: function(data) {...}
};
Cart.init();

While Singleton vs. Module Pattern can be a legitimate question, with the example you gave, this question should be reworded as Singleton vs IIFE, as it's not the module pattern per se, but rather the IIFE that the module pattern is wrapped in that is keeping cruft out of your Cart singleton. And even then, it's not a vs. kind of question -- both IIFE and Singleton can be used together. The purpose of the IIFE is just to keep stuff out of global scope.
So ..., you can package your singleton Code into an IIFE as follows
;(function(){
var Cart = {
settings: {
// Your code ...
};
Cart.init();
})();
In this case, you're writing your code as a Singleton but wrapping it in an IIFE, and there is no usage of global scope. The IIFE is completely independent of how you choose to write and organize your code. You would need a different example for a Singleton vs. Module Pattern question.

IIFE (immediately invoked function expression):
(function() {
console.log('run this in your browser console')
})()
Module pattern:
var module = (function () {
var privateScopeVar = 1 // scope of the IIF
// the 'this' context in this scope is the global object (e.g. window)
// returns literal object who's method's scopes are lexically bound
// to the IIF scope
return {
publicMethod: () => privateScopeVar // publicMethod scope can access IIF scope
}
})()
Singleton Literal + Singleton Literal that cannot be overwritten if included/imported more than once in EcmaScrip5:
var singleInstance = { firstName: 'Greg' }
var singleInstance = singleInstance || { firstName: 'Greg' }
Singleton Literal that cannot be overwritten or initialized more than once in EcmaScrip6:
const singleInstance = {
firstName: 'Greg',
called: false,
init: () => {
if (!this.called) {
console.log('only once')
this.called = true
}
}
}
// of course singleInstance.called = false; singleInstance.init() is always possible
Singleton inside IIF (provides private state)
const singleton = (function () {
// IIF private scope ensures there is a single instance ever
var storedInstance
// Also some private state for the singleton instance as well
const firstName = 'Greg'
// literal object that holds constructor function
const Singleton = {
getInstance: () => {
if (!storedInstance) {
storedInstance= {
getName: () => firstName
}
}
return storedInstance
}
}
return Singleton
})()

Related

JavaScript module pattern - returned object === module || facade

I am a little confused here. Following the module pattern in JS, a module is normally a returned object from an anonymous function that is immediately executed. But what if I don't want to execute the function and instead call it whenever I need to e.g. window.onload.
var module = function (args) {
//private members
return {
//public members
};
};
var module_instance = module (args); // module instance or facade instance?
Are there any problems with this implementation? Is there a different, more efficient way to do this?
Also, following the previos block of code, what if I call the function again and asign the returned value to another variable:
var module_instance2 = module (args);
does that mean I now have a 2nd facade of the function or is it a new function altogether?
Cheers!
That function is the constructor of your module so each time you call that function, a new separate instance of the module is created and assigned to the receiving variable.
There is not any problem with this implementation (actually it is very common,), and you can use it wherever in your program to obtain a new instance of that module.
Best.
The module pattern is similar to namespaces in other languages, and is used to prevent global variable pollution and as a method of encapsulation.
window.module1 = (function() {} {
var version = "0.0.1";
function func1 () {};
function func2 () {};
return = {
version: version,
func1: func1,
func2: func2,
};
})()
You could have a Function DeclareModule() that defines a module on the window object.
var DeclareModule = function(name, content) {
if (typeof content === 'object') {
window[name] = content;
} else if (typeof content === 'function') {
window[name] = content();
}
};
//Declared by object
DeclareModule("module1", {
version: "0.0.1",
func1: function () {},
func2: function () {}
});
//Declared by function
DeclareModule("module1", function () {
var version = "0.0.1";
function func1 () {};
function func2 () {};
return {
version: version,
func1: func1,
func2: func2
};
});
Have a look at AMD and CommonJS modules, or an article by Addy Osmani.

Prototype Pattern and "this"

I'm trying to create a client-side api for a web control using the Prototype pattern. However I want to make life easier by not having to manage "this".
This is some sample code (i have commented the problematic line):
MyObject = function ()
{
MyObject.initializeBase(this);
this._someProperty = null;
};
MyObject.prototype = {
initialize: function()
{
// Init
},
get_someProperty: function()
{
return this._someProperty;
},
set_someProperty: function(value)
{
this._someProperty = value;
},
doSomething: function ()
{
$('.some-class').each(function ()
{
$(this).click(this.doClick); // this.doClick is wrong
});
},
doClick: function ()
{
alert('Hello World');
}
};
Normally, using the revealing module pattern I would declare a private variable:
var that = this;
Can I do something similar with the Prototype pattern?
You can do the exact same thing you are used to, just do it within the doSomething method:
doSomething: function ()
{
var instance = this;
$('.some-class').each(function ()
{
$(this).click(instance.doClick);
});
},
This approach has nothing to with prototype or not, it's just how to manage context with nested functions. So when a function on a prototype (method) has nested functions within in, you may have to preserve the context this at any of those level if you want to access it in a nested scope.
ES5's Function.prototype.bind() might be an option for you. You could go like
doSomething: function ()
{
$('.some-class').each(function(_, node)
{
$(node).click(this.doClick); // this.doClick is right
}.bind(this));
},
Now, we proxied each event handler by invoking .bind() and as a result, we call it in the context of the prototype object. The caveat here is, you no longer have this referencing the actuall DOM node, so we need to use the passed in arguments from jQuery instead.

Way to make global private variables in javascript?

Is there a way to create private global variables in JavaScript? I have tried looking around, and I keep bumping into talk of constructors - which don't seem too global.
Thanks
Not sure what your use case is. I'll assume you have a js script file containing some functions and variables and you want to expose some of those globally, but keep the rest private to your script file. You can achieve this with a closure. Basically you create a function that you execute immediately. Inside the function you place your original code. You then export the functions you need into the global scope.
// Define a function, evaluate it inside of parenthesis
// and execute immediately.
(function(export) {
var myPrivateVariable = 10;
function myPrivateFunction(param) {
return param + myPrivateVariable;
}
export.myGlobalFunction = function(someNumber) {
return myPrivateFunction(someNumber);
};
})(this); // The *this* keyword points to *window* which
// is *the* global scope (global object) in a web browser
// Here it is a parameter - the *export* variable inside the function.
// This is executed in the global scope
myGlobalFunction(2); // yields 12 (i.e. 2 + 10)
myPrivateVariable; // Error, doesn't exist in the global scope
myPrivateFunction(2) // Error, doesn't exist in the global scope
To answer your question, no, that is not possible as there are no access modifiers in javascript. A variable declared in global scope is accessible to any function.
As pointed out in the comments to this answer, you can create objects which have private members. Crockford has a page on private members in Javascript. He uses the following code to illustrate his point:
function Container(param) {
// private method
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
// privileged method
this.service = function () {
return dec() ? that.member : null;
};
}
In the above example, param, secret, and that are all private in that they are not accessible from the outside. To be more clear, these variables can only be accessed by privileged or private methods, the difference being that privileged methods can be called from any instance of the object. As is suggested in the comments, this is achievable by using closures.
Quoting from Crockford for a quick explanation on closures, but you can find plenty of related questions.
What this means is that an inner function always has access to the
vars and parameters of its outer function, even after the outer
function has returned.
in order to have private members. you need to use closures.
following code help you understanding the concept.
function CustomArray () {
this.array = [];
var privateData = 'default data';
this.getPrivateData = function () {
return privateData;
};
this.setPrivateData = function (data) {
privateData = data;
};
};
CustomArray.prototype.push = function (data) {
this.array.push(data);
};
CustomArray.prototype.unshift = function (data) {
this.array.unshift(data);
};
CustomArray.prototype.pop = function () {
this.array.pop();
};
CustomArray.prototype.shift = function () {
this.array.shift();
};
CustomArray.prototype.print = function () {
console.log(this.array.join(','));
};
var array = new CustomArray();
array.push(10);
array.push(20);
array.push(30);
array.push(5);
array.unshift(3);
array.unshift(2);
array.unshift(1);
array.unshift(0);
array.pop();
array.shift();
array.print();
console.log(array.getPrivateData());// default data
array.setPrivateData('am new private data');
console.log(array.getPrivateData());//am new private data

Is it possible to pass execution context of the immediately invoked function expression

Consider the following code:
(function() {
var a = 5;
var someFunc = function() { ... };
function anotherFunc() {
...
};
})();
window.myGlobalObj = {
init: function() {
// and somehow here I want to access to the IIFE context
}
};
I want to have the execution context of IIFE in my global object. I do have access to function expression and object itself so I can pass or modify something to make it work (and no, I can't rewrite everything inside the object or function).
Is it even possible?
The only way I see how that's poosible is by using eval to simulate dynamic scopes. Do this (note that the IIFE must be placed after the global object):
window.myGlobalObj = {
init: function() {
// and somehow here I want to access to the IIFE context
}
};
(function() {
var a = 5;
var someFunc = function() { ... };
function anotherFunc() {
...
};
eval("(" + String(window.myGlobalObj.init) + ")").call(window.myGlobalObj);
})();
Here's a reference as on how to use dynamic scopes: Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?
Edit: I've included an example to demonstrate the power of using dynamic scopes in JavaScript. You can play with the fiddle too.
var o = {
init: function () {
alert(a + b === this.x); // alerts true
},
x: 5
};
(function () {
var a = 2;
var b = 3;
eval("(" + String(o.init) + ")").call(o);
}());
The "contents" of your IIFE, i.e., a, someFunc, etc., are local to that function scope, so you can only access them within that scope. But you can assign window.myGlobalObj inside the IIFE:
(function() {
var a = 5;
var someFunc = function() { ... };
function anotherFunc() {
...
};
window.myGlobalObj = {
init: function() {
// and somehow here I want to access to the IIFE context
}
};
})();
Then the init function will have access to those variables since they are in its containing scope.
EDIT: if you can't move the definition of myGlobalObj into the IIFE the only thing I can think of is to use the IIFE to create a second global object that you access from myGlobalObj:
(function() {
var a = 5;
var someFunc = function() { ... };
function anotherFunc() {
...
};
// create a global object that reveals only the parts that you want
// to be public
window.mySecondObject = {
someFunc : someFunc,
anotherFunc : anotherFunc
};
})();
window.myGlobalObj = {
init: function() {
window.mySecondObject.someFunc();
}
};
No. It is not possible. The context you want to access is called closure and can be accessed only within the function (in your case, the anonymous function (IIFE how you call it)). For more about closures follow the excellent Douglas Crockfords The Javascript programming language video tutorial.
You will have to place those attributes to some shared object.

How to create private variables within a namespace?

For my web application, I am creating a namespace in JavaScript like so:
var com = {example: {}};
com.example.func1 = function(args) { ... }
com.example.func2 = function(args) { ... }
com.example.func3 = function(args) { ... }
I also want to create "private" (I know this doesn't exist in JS) namespace variables but am not sure what's the best design pattern to use.
Would it be:
com.example._var1 = null;
Or would the design pattern be something else?
Douglas Crockford popularized so called Module Pattern where you can create objects with "private" variables:
myModule = function () {
//"private" variable:
var myPrivateVar = "I can be accessed only from within myModule."
return {
myPublicProperty: "I'm accessible as myModule.myPublicProperty"
}
};
}(); // the parens here cause the anonymous function to execute and return
But as you said Javascript doesn't truly have private variables and I think this is somewhat of a cludge, which break other things. Just try to inherit from that class, for example.
Closures are frequently used like this to simulate private variables:
var com = {
example: (function() {
var that = {};
// This variable will be captured in the closure and
// inaccessible from outside, but will be accessible
// from all closures defined in this one.
var privateVar1;
that.func1 = function(args) { ... };
that.func2 = function(args) { ... } ;
return that;
})()
};
After 7 years this might come quite late, but I think this might be useful for other programmers with a similar problem.
A few days ago I came up with the following function:
{
let id = 0; // declaring with let, so that id is not available from outside of this scope
var getId = function () { // declaring its accessor method as var so it is actually available from outside this scope
id++;
console.log('Returning ID: ', id);
return id;
}
}
This might only be useful if you are in a global scope and want to declare a variable that is not accessible from anywhere except your function that sets the value of id one up and returns its value.

Categories