How to communicate between javascript modules...? - javascript

In my application are a couple of modules for their own responsibility, and that's where I have some confusion..
How to communicate between modules?
How to inform or listen modules between to take decision for appropriate scenario..?
example:
module 1,
var MyModule1 = (function() {
var myPrivateData = 303;
function myPrivateFunction() {
alert('private');
}
return {
myPublicData : 42,
myPublicFunction : function() {
alert('public');
}
};
})();
Module 2
var MyModule2 = (function() {
var myPrivateName = privatized;
function myPrivateFunction() {
alert(myPrivateName) ;
}
return {
myPublicData : 42,
myPublicFunction : function() {
alert('public');
}
};
})();
How can I make them both communicate and listen to each other..? Can anyone please clarify with some small example? I need to share the privateData shared to module2 and myPrivate name shared with module1 and in case of any click event to be triggered.
Thanks in advance!

Here is basic concept of loosely coupled modules organization inside the browser:
When code inside module1 needs to notify others about some event it will do this:
$(document).trigger( "some:event", someData);
And module2 if it needs to be notified about "some:event" shall do this in its code on its initialization:
$(document).on( "some:event", function(evt,someData) {
// ... do something with the data ...
} );
In this schema two modules are completely independent. The only thing they shall to know are names of events they are communicating with.

Something like this
var ParentClass = (function() {
var privateVariable = 'toto';
this.publicVariable = 'titi';
this.ChildClass = new ChildClass(this);
this.ChildClass.execute();
});
function ChildClass(parent) { this.parent = parent; return this; };
ChildClass.prototype.execute = function() {
alert (this.parent.publicVariable); // show titi
};
ParentClass();

Related

Patterns for avoiding name-space pollution

This article describes a number of patterns to avoid name-space pollution. I listed the patterns below with part of the sample code that was given in the article.
My question is: is there any commonly accepted 'best' way? What are the considerations when choosing one for my project?
Direct Assignment
var myApp = {}
myApp.id = 0;
myApp.next = function() {
return myApp.id++;
}
Using Object Literal Notation
var myApp = {
id: 0,
next: function() {
return this.id++;
}
}
The Module Pattern
var myApp = (function() {
var id= 0;
return {
next: function() {
return id++;
},
};
})();
Namespace Argument
var myApp = {};
(function(context) {
var id = 0;
context.next = function() {
return id++;
};
})(myApp);
this as a Namespace Proxy
var myApp = {};
(function() {
var id = 0;
this.next = function() {
return id++;
};
this.reset = function() {
id = 0;
}
}).apply(myApp);
The method I currently use
I used the following method in my own project. Is it bad?
function MyObj(){
this.someProperty = 'something';
}
MyObj.prototype.someFunction = function(){
this.someProperty =5;
}
myApp = new MyObj();
There is no commonly accepted best way. Sorry.
As Pointy said, your method involves creating the MyObj constructor function, which presumably will never be used again, as well as the myApp namespace object. It has at least one other minor disadvantage: you can't prevent yourself or someone else using the code from calling MyObj again, which is strange for something that's supposed to be your namespace.
Any of the IIFE-based solution should work fine, and they're mostly interchangeable. The module (or revealing module) is arguably the simplest. The namespace argument allows you to break a module over multiple files, something I choose never to do, but if that's what you want, it might be useful. I can't see any real advantages to the "this as a Namespace Proxy" method.

How do you use class based OOP JavaScript in the browser?

I've been converting my procedural JS functions into a class and now I'd like to know when to instantiate it.
Here is my class:
MyProject = function() {};
MyProject.prototype.myProperty = "10";
MyProject.prototype.myMethod = function (value) {
// do something
}
Here is my HTML page:
<script src="javascriptfilesdirectory/MyProject.js"/>
<script>
function initialize() {
myProject = new MyProject();
}
</script>
<body onload="initialize()" >
My question is do I intialize it on page load and create a local variable as shown above or do I initialize it in the JS class file?
Here is my JS file:
MyProject = function() {};
MyProject.prototype.myProperty = "10";
MyProject.prototype.myMethod = function (value) {
// do something
}
myProject = new MyProject();
Also, I'm talking in general and in this case it's a singleton. I only want one copy of it in use.
If you really want it as a singleton, you can do it easier than that, something like:
var myProject = new (function() {
this.myProperty = "10";
this.myMethod = function(value) { }
})();
Your "class" is only defined long enough to assign it once, since you're never going to instantiate a second copy.
For a non-singleton, I tend to follow the pattern found on the TypeScript page:
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
var greeter = new Greeter("world");
Also, I'm talking in general and in this case it's a singleton. I only want one copy of it in use.
In that case, just directly create the object:
var myProject = {
myProperty: "10",
myMethod: function() { ... }
};
When and where you create the object doesn't matter, as long as you have access to it when and where you need it.

What type of pattern does this JS adhere to?

I came across code similar to this recently,
// Simplified example..
var Application =
{
MemberVar1: null,
MemberVar2: null,
Initialize: function ()
{
Application.MemberVar1 = 'Foo';
Application.MemberVar2 = 'Bar';
console.log("Initializing..");
Application.GetMemberVars();
},
GetMemberVars: function ()
{
console.log(Application.MemberVar1 + ' ' + Application.MemberVar2);
}
};
$(Application.Initialize);
What is the name of this pattern/method/style? Utilizing OOP principles without using a style I've seen before, such as prototyping. What are the benefits of this style as opposed to other popular ones?
It's a simple one-off object literal that's being created... they can contain functions... perhaps that's what threw you.
The last line merely passes the Application.Initialize function to jQuery as a $(document).ready callback function
In light of the comments below, this is what the code actually does (and how you can write it a lot shorter/easier)
$(function()
{
console.log("Initializing..");
console.log("Foo Bar");//replace this with variables you declare #top of anon. function if you want
});
As a module (you can find out more about the module pattern here):
var Application = (function()
{
var memberVar1, memberVar2,
getMemberVars = function()
{
return memberVar1 + ' ' + memberVar2;
};
return {init: function()
{
memberVar1 = 'Foo';
memberVar2 = 'Bar';
console.log('initializing...');
console.log(getMemberVars());
}};
}());
$(Application.init);
Application is now an object literal, with only 1 property (init): a function that, because it was declared within the scope of that IIFE, has access to all variables local to that scope. That's the magic of closures for you. You can easily add getters and setters for the member vars, too:
var Application = (function()
{
var memberVars = {},//turned into object literal...
getMemberVars = function(all)
{
var i;
if(typeof all === 'string' || typeof all === 'number')
{
return memberVars[all];
}
all = [];
for (i in memberVars)
{
if (memberVars.hasOwnProperty(i))
{
all.push(memberVars[i]);
}
}
return all;//or all.join(' '), as you please
},
get = function(name)
{
return typeof name === 'undefined' ? name : memberVars[name];
},
set = function(name, val)
{
memberVars[name] = val;
};
return {init: function()
{
memberVars.one = 'Foo';
memberVars.two = 'Bar';
console.log('initializing...');
console.log(getMemberVars().join(' '));
},
get: get,
set: set};//just add getter and setter here
}());
This has the same behavior as your code:
var Application = (function() {
var app = {
MemberVar1: null,
MemberVar2: null,
GetMemberVars: function() { /* ... */},
Initialize: function() {
this.MemberVar1 = 'Foo';
this.MemberVar2 = 'Bar';
console.log('Initializing..');
this.getMemberVars();
}
};
$(function() {app.Initialize();});
return app;
}());
But there's a good chance that you don't really want that Initialize function hanging around. So this would simplify it:
var Application = (function() {
var app = {
MemberVar1: null,
MemberVar2: null,
GetMemberVars: function() { /* ... */}
};
$(function() {
app.MemberVar1 = 'Foo';
app.MemberVar2 = 'Bar';
console.log('Initializing..');
app.getMemberVars();
});
return app;
}());
And unless you're actually worried about code trying to access Application.MemberVar1, etc before jQuery's document.ready event, you can simplify it further to this:
var Application = (function() {
var app = {
GetMemberVars: function() { /* ... */}
};
$(function() {
app.MemberVar1 = 'Foo';
app.MemberVar2 = 'Bar';
console.log('Initializing..');
app.getMemberVars();
});
return app;
}());
I'm assuming that defining those MemberVars took some real work, and were not simple strings as in the example. If that's not the case, then I would switch this last to
var Application = (function() {
var app = {
MemberVar1: 'Foo';
MemberVar2: 'Bar';
GetMemberVars: function() { /* ... */}
};
$(function() {
console.log('Initializing..');
app.getMemberVars();
});
return app;
}());
You don't need to use prototype if you are going to use only one instance of some object.
In this case it's pretty clear the Application object is something unique and the author didn't intend there were going to be any additional copies of Application created.
Talking about style... that capital camel case looks ugly. The common agreement is to use CapitalCamelCase only for object constructors. I personally think it's ok to use for unique objects with logic too (Application). But using it for function names and variables should be avoided.
Talking about patterns... it's close to Singleton pattern. But don't think too much about it. All those OOP patterns from Java world lose part of their appeal in JS world. Some of them disintegrate completely. Concentrate on JS ways of solving problems.

Invoke javascript function from string

I have the following code in my javascript module, however this requires me to make the functions visible to the outside world.
var mymodule = function() {
var self = null,
init = function () {
self = this;
$('.actionButton').click(function () {
var worklistId = $(this).data('worklistid'),
action = $(this).data('action');
self[action] && self[action](worklistId); //watchout methods marked as not used are used by this invocation
})
},
send = function () {
// some logic
},
finish = function () {
// some logic
},
delete = function () {
// some logic
};
return {
init: init,
send: send,
finish: finish,
delete: delete
};
}();
mymodule.init();
So the only thing I want to return in my module is the init function. However when I do this I cant invoke the functions, because the object (self) only contains the init function visible on the outside.
return {
init: init
};
Is there any solution to invoke my functions like this without making them visible to the outside world? Please no if else statements, because my workflow is bigger then the 3 actions in this example. I want to make my module as closed as possible because this reduces the dependencies.
Update
Here is a updated jsfiddle with one of the proposed solutions, however this is giving me another issue. http://jsfiddle.net/marcofranssen/bU2Ke/
Something like this would work:
var mymodule = function() {
var self = this;
init = function () {
$('.actionButton').click(function () {
var worklistId = $(this).data('worklistid'), action = $(this).data('action');
self[action] && self[action](worklistId); //watchout methods marked as not used are used by this invocation
})
}
self.send = function () {
console.log('send');
}
self.finish = function () {
console.log('finish');
}
self.delete = function (item) {
console.log('delete');
};
return {
init: init,
};
}();
mymodule.init();​
Here's the fiddle:
http://jsfiddle.net/yngvebn/SRqN3/
By setting the self-variable to this, outside the init-function, and attaching the send, finish and delete functions to self, you can use the self[action] syntax from within the init-function
Yes, there is an easy (but perhaps slightly messy) way you can do this without making the functions visible to the global object:
var privateFunctions = { deleter: deleter, send: send};
Then, instead of self[action]();, just do privateFunctions[action](); and you're good to go.
Note that I changed delete to deleter, because delete is a reserved keyword...
var mymodule = function() {
var self = {},
init = function () {
$('.actionButton').click(function () {
var worklistId = $(this).data('worklistid'),
action = $(this).data('action');
self[action] && self[action](worklistId); //watchout methods marked as not used are used by this invocation
})
};
self.send = function () {
// some logic
};
self.finish = function () {
// some logic
};
self.delete = function () {
// some logic
};
return{
init:init
}
}();
mymodule.init();
This should Work!!
Even if you return an object just with the init property and you populate the rest dynamically such that your module uses them, you would still be making them visible to the outside at runtime. Anyone who wants to debug your module would easily get to them.
You can still create anonymous methods at runtime and they would also be visible together with their implementation.
In your code example, it is vague what "self" really is. You should keep it simple, use encapsulated functions as "private" methods and return a "public" (or "privileged" as Crockford calls it) function that have access to them.
This is the YUI way of doing singletons with private functions and variables. Example pattern:
var mymodule = (function() {
var internal = {
'send': function() {},
'finish': function() {},
'delete': function() {}
};
return {
'init': function(action) {
// access to internals, f.ex:
if ( internal.hasOwnProperty(action) ) {
internal[action].call(this); // bring the caller context
}
}
};
}());
mymodule.init('send');

JavaScript Namespace

I want to create a global namespace for my application and in that namespace I want other namespaces:
E.g.
Dashboard.Ajax.Post()
Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent();
I also want to place them in seperate files:
Ajax.js
RetrieveContent.js
However I have tried using this method, however it won't work because the same variable name is being used for the namespace in 2 seperate places. Can anyone offer an alternative?
Thanks.
You just need to make sure that you don't stomp on your namespace object if it's already been created. Something like this would work:
(function() {
// private vars can go in here
Dashboard = Dashboard || {};
Dashboard.Ajax = {
Post: function() {
...
}
};
})();
And the RetrieveContent file would be defined similarly.
Here is a very good article on various "Module Patterns" in JavaScript. There is a very nice little section on how you can augment modules, or namespaces and maintain a cross-file private state. That is to say, the code in separate files will be executed sequentially and properly augment the namespace after it is executed.
I have not explored this technique thoroughly so no promises... but here is the basic idea.
dashboard.js
(function(window){
var dashboard = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
window.Dashboard = dashboard;
})(window);
dashboard.ajax.js
var dashboard = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || function () {
delete my._private;
delete my._seal;
delete my._unseal;
},
_unseal = my._unseal = my._unseal || function () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// permanent access to _private, _seal, and _unseal
my.ajax = function(){
// ...
}
return my;
}(dashboard || {}));
dashboard.retrieveContent.js
var dashboard = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || function () {
delete my._private;
delete my._seal;
delete my._unseal;
},
_unseal = my._unseal = my._unseal || function () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// permanent access to _private, _seal, and _unseal
my.retrieveContent = function(){
// ...
}
return my;
}(dashboard || {}));
The Yahoo Namespace function is exactly designed for this problem.
Added:
The source of the function is available. You can copy it into your own code if you want, change the root from YAHOO to something else, etc.
There are several libraries that already offer this sort of functionality if you want to use or examine a pre-baked (that is, a tested) solution.
YUI.attribute and YUI.base
dojo.mixin
underscore.extend
jQuery.extend
goog.provide and goog.object.extend
The simplest and most bug free one to get going with is probably jQuery.extend, with the deep argument set to true. (The reason I say it is bug free is not because I think that jQuery.extend suffers from less bugs than any of the other libraries -- but because it offers a clear option to deep copy attributes from the sender to the receiver -- which most of the other libraries explicitly do not provide. This will prevent many hard-to-diagnose bugs from cropping up in your program later because you used a shallow-copy extend and now have functions executing in contexts you weren't expecting them to be executing in. (If however you are cognizant of how you will be extending your base library while designing your methods, this should not be a problem.)
With the NS object created, you should just be able to add to it from where ever. Although you may want to try var NS = NS || {}; to ensure the NS object exists and isn't overwritten.
// NS is a global variable for a namespace for the app's code
var NS = NS || {};
NS.Obj = (function() {
// Private vars and methods always available to returned object via closure
var foo; // ...
// Methods in here are public
return {
method: function() {
}
};
}());
You could do something like this...
HTML page using namespaced library:
<html>
<head>
<title>javascript namespacing</title>
<script src="dashboard.js" type="text/javascript"></script>
<script src="ajax.js" type="text/javascript"></script>
<script src="retrieve_content.js" type="text/javascript"></script>
<script type="text/javascript">
alert(Dashboard.Ajax.Post());
alert(Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent());
Dashboard.RetrieveContent.Settings.Timeout = 1500;
alert(Dashboard.RetrieveContent.Settings.Timeout);
</script>
</head>
<body>
whatever...
</body>
</html>
Dashboard.js:
(function(window, undefined){
var dashboard = {};
window.Dashboard = dashboard;
})(window);
Ajax.js:
(function(){
var ajax = {};
ajax.Post = function() { return "Posted!" };
window.Dashboard.Ajax = ajax
})();
Retrieve_Content.js:
(function(){
var retrieveContent = {};
retrieveContent.RefreshSalespersonPerformanceContent = function() {
return "content retrieved"
};
var _contentType;
var _timeout;
retrieveContent.Settings = {
"ContentType": function(contentType) { _contentType = contentType; },
"ContentType": function() { return _contentType; },
"Timeout": function(timeout) { _timeout = timeout; },
"Timeout": function() { return _timeout; }
};
window.Dashboard.RetrieveContent = retrieveContent;
})();
The Dashboard.js acts as the starting point for all namespaces under it. The rest are defined in their respective files. In the Retrieve_Content.js, I added some extra properties in there under Settings to give an idea of how to do that, if needed.
I believe the module pattern might be right up your alley. Here's a good article regarding different module patterns.
http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
I highly recommend you use this technique:
https://github.com/mckoss/namespace
namespace.lookup('com.mydomain.mymodule').define(function (ns) {
var external = namespace.lookup('com.domain.external-module');
function myFunction() {
...
}
...
ns.extend({
'myFunction': myFunction,
...
});
});
I've been using this pattern for a couple of years; I wish more libraries would do the same thing; it's made it much easier for me to share code across my different projects as well.
i wrote this function to simplify creating namespaces. Mabey it will help you.
function ns(nsstr) {
var t = nsstr.split('.');
var obj = window[t[0]] = window[t[0]] || {};
for (var i = 1; i < t.length; i++) {
obj[t[i]] = obj[t[i]] || {};
obj = obj[t[i]];
}
}
ns('mynamespace.isawesome.andgreat.andstuff');
mynamespace.isawesome.andgreat.andstuff = 3;
console.log(mynamespace.isawesome.andgreat.andstuff);
bob.js can help in defining your namespaces (among others):
bob.ns.setNs('Dashboard.Ajax', {
Post: function () { /*...*/ }
});
bob.ns.setNs('Dashboard.RetrieveContent', {
RefreshSalespersonPerformanceContent: function () { /*...*/ }
});
Implementation:
namespace = function(packageName)
{
// Local variables.
var layers, layer, currentLayer, i;
// Split the given string into an array.
// Each element represents a namespace layer.
layers = packageName.split('.');
// If the top layer does not exist in the global namespace.
if (eval("typeof " + layers[0]) === 'undefined')
{
// Define the top layer in the global namesapce.
eval(layers[0] + " = {};");
}
// Assign the top layer to 'currentLayer'.
eval("currentLayer = " + layers[0] + ";");
for (i = 1; i < layers.length; ++i)
{
// A layer name.
layer = layers[i];
// If the layer does not exist under the current layer.
if (!(layer in currentLayer))
{
// Add the layer under the current layer.
currentLayer[layer] = {};
}
// Down to the next layer.
currentLayer = currentLayer[layer];
}
// Return the hash object that represents the last layer.
return currentLayer;
};
Result:
namespace('Dashboard.Ajax').Post = function() {
......
};
namespace('Dashboard.RetrieveContent').RefreshSalespersonPerformanceContent = function() {
......
};
Gist:
namespace.js

Categories

Resources