How do I create a namespace in JavaScript? - javascript

I want to access variables by using
MyNamespace.variable1
that are globally accessible. I believe Drupal does something similar, no?

var MyNamespace = {};
MyNamespace.variable1 = value1;
It's just an object really.

What Drupal does is using the following code:
var Drupal = Drupal || { 'settings': {}, 'behaviors': {}, 'locale': {} };
Drupal.attachBehaviors = function (context, settings) {
context = context || document;
settings = settings || Drupal.settings;
// Execute all of them.
$.each(Drupal.behaviors, function () {
if ($.isFunction(this.attach)) {
this.attach(context, settings);
}
});
};
Drupal.detachBehaviors = function (context, settings, trigger) {
context = context || document;
settings = settings || Drupal.settings;
trigger = trigger || 'unload';
// Execute all of them.
$.each(Drupal.behaviors, function () {
if ($.isFunction(this.detach)) {
this.detach(context, settings, trigger);
}
});
};
// …
Using similar code, you can emulate namespaces using JavaScript.

Also, if you have many JS files that each add a "namespace" or Object into a top level package you can do stuff like this:
ModuleA.js
// if Modules is null, create a new object, else use the currently defined instance
var Modules = Modules || {};
Modules.A = {};
// sample instance variable
Modules.A.instanceVar;
// sample function
Modules.A.myFunc = function(param1, param2) {
// do something
}
ModuleB.js
// if Modules is null, create a new object, else use the currently defined instance
var Modules = Modules || {};
Modules.B = {};
// sample instance variable
Modules.B.instanceVar;
// sample function
Modules.B.myFunc = function(param1, param2) {
// do something
}
Then you can of course just call them as you need them Modules.A.myFunc() or Modules.B.myFunc() or Modules.B.instnaceVar = 20;. So you can encapsulate functions as well as variables.
For my code I like to have a root Object, (i.e ) and then added "classes" (objects) to it so that everything has a nice "package like", "OOP" structure to it.

Just create an object. E.g.:
var MyNamespace = {};
MyNamespace.variable1 = ...

Related

Creating an instance of multiple javascript modules

This related to javascript code. My application has many sub applications that are sometimes used more then once on a page. An example would be an application that allows the user to search for some data and displaying the search results. This application my be used in multiple places on a page to search for different types of data.
Each sub application typically includes many javascript modules each in a separate file. I have experienced with many different module patterns to try to create a separate instance of multiple modules/files but with no success. There is much advice online how to create multiple instances of objects, using factory pattern etc but I have not been able to make it work with the name space structure and module pattern my application. See example below.
The question is how can you create multiple independent instances of SubAppA including all its sub modules.
(New file)
var MainApp = MainApp || {};
MainApp.SubAppA = MainApp.SubAppA || {};
MainApp.SubAppA.Config = (function () {
function A () { ... };
function B () { ... };
return {
A : A,
B : B
}
})();
(New file)
var MainApp = MainApp || {};
MainApp.SubAppA = MainApp.SubAppA || {};
MainApp.SubAppA.GetData = (function () {
function A () { ... };
function B () { ... };
return {
A : A,
B : B
}
})();
(New file)
var MainApp = MainApp || {};
MainApp.SubAppA = MainApp.SubAppA || {};
MainApp.SubAppA.DisplayData = (function () {
etc.....
Many thanks in advance
--- Additional information after solution proposed by MikeM -----
Thanks MikeM, you answer gave me a better understanding but when trying to implement it using my existing name space structure, I can't get the modules to communicate with each other. I tried the following:
//Solution $S.AS - New file
var $S = $S || {};
$S.AS = $S.AS || {};
$S.AS.DataStore = function () {
var _SomeVar = "Default";
function SetVar (Data) {
_SomeVar = Data;
};
function GetVar () {
return _SomeVar;
};
return {
SetVar : SetVar,
GetVar : GetVar
}
};
//Solution $S.AS - New file
var $S = $S || {};
$S.AS = $S.AS || {};
$S.AS.ManageData = function () {
function StoreData (Data) {
console.log($S.AS.DataStore); //outputs f ()
//Does now work since DataStore is now a function
//$S.AS.DataStore.SetVar(Data);
$S.AS.DataStore().SetVar(Data);
};
function DisplayData () {
//Does now work since DataStore is now a function
//var SomeVar = $S.AS.DataStore.GetVar();
//Does not work, still outputs "Default"
var SomeVar = $S.AS.DataStore().GetVar();
console.log(SomeVar);
};
return {
StoreData : StoreData,
DisplayData : DisplayData
}
};
//Solution $S.AS - New file - The contructor function for AS
var MainApp = MainApp || {};
MainApp.S = MainApp.S || {};
MainApp.S.AS = MainApp.S.AS || {};
MainApp.S.AS = function () {
this.DataStore = $S.AS.DataStore();
this.ManageData = $S.AS.ManageData();
//additional modules
};
//Main/Page specific code - creating the different instances
MainApp.S.AS_1 = new MainApp.S.AS();
MainApp.S.AS_2 = new MainApp.S.AS();
//Attemps to store and retrieve data
//Stores AAA in the DataStore module
MainApp.S.AS_1.ManageData.StoreData("AAA");
//Stores BBB in the DataStore module
MainApp.S.AS_2.ManageData.StoreData("BBB");
//Not working, ouputs: "Default" (Desired result is "AAA")
MainApp.S.AS_1.ManageData.DisplayData();
//Not working, ouputs: "Default" (Desired result is "BBB");
MainApp.S.AS_2.ManageData.DisplayData();
I think I understand why "Default" is output (the call is made to the original variable stored at page load) but not how to fix it.
For context, I have a custom php script that concatenates all the JS files required for a page and then adds them as a single tag to the page. I thought this would speed up script loading, in particular since most of my pages will have 50+ JS files/modules. A typical Name space structure for a page will look as follows (but with a lot more modules):
MainApp = {
//Page specific or utility modules
ModuleA : [ func / module ],
ModuleB : [ func / module ],
ModuleC : [ func / module ],
ModuleD : [ func / module ],
//Resulable applications consisting of multiple modules
SubAppA : {
ModuleA : [ func / module ],
ModuleB : [ func / module ],
ModuleC : [ func / module ],
ModuleD : [ func / module ],
},
SubAppB : {
ModuleA : [ func / module ],
ModuleB : [ func / module ],
ModuleC : [ func / module ],
ModuleD : [ func / module ],
}
}
I was hoping that I can somehow preserver this structure to avoid the risk of conflicting module names. I am happy to change the structure of the modules themselves (e.g. from IIFE to something else) to get an solution to the question.
Thanks
Thanks MikeM, it is now working, very helpful! Yes I am aware of that I need to look at ES modules closer. I learned to code recently to test an idea after working in a completely different field for 17 years so some shortcuts had to be made ...
Here is a write up of my implementation step by step in case it helps someone else that is not too familiar with Javascript modules.
The objectives of the question were to:
Enable multiple instances of an application to exist on a page where each application consists of multiple modules
Enable the modules to call methods in other modules
Make it easy to instantiate (create a new version) of the application
Some things to consider in relation to below solution:
Rather than static calls to methods in other module (e.g. ReuseApp.App1.Display.DisplayData(Data) each module stores an internal reference of the top object of the newly created instance of the application (e.g. _App.Display.DisplayData(Data).
Module are created without the immediately evoked feature (i.e. no IIFE pattern).
A construction function referencing all required module are required. This function will send the newly created object (this) into each module e.g. this.Config = ReuseApps.App1.Config(this);
Each module to take this reference as a parameter (App) and store it within the module (_App). _App will be used when calling other module methods.
Step by step by step guide:
STEP A: Create modules using the following pattern (disregard multi level namespaces if not needed):
//Separate file e.g. Config.js
const ReuseApps = ReuseApps || {};
ReuseApps.App1 = ReuseApps.App1 || {};
ReuseApps.App1.Config = function (App) {
let _App; //Used to call other module methods
let _Settings = {};
function Init (Settings) {
_Settings = Settings;
//Configure app e.g. store element refs, add event handlers etc
var Data = GetDataFromSomeWhere();
//Call another module using the _App reference
_App.Display.DisplayData(Data);
}
_App = App;
Return {
Init : Init
}
}
//Separate file e.g. Display.js
const ReuseApps = ReuseApps || {};
ReuseApps.App1 = ReuseApps.App1 || {};
ReuseApps.App1.Display = function (App) {
let _App; //Used to call other module methods
function DisplayData (Data) {
//Display Data in DOM
}
_App = App;
return {
DisplayData : DisplayData
}
}
STEP B: Create the construction function required to create a new instance of application
//can be in separate file e.g. app1_create.js
function App1Create () {
this.Config = ReuseApps.App1.Config(this);
this.Display = ReuseApps.App1.Display(this);
//etc more modules …
}
STEP C: Creating a separate instance of above application in the main code
//Create new instance using constructur function
//(Assumes the MainApp namespace exists already)
MainApp.ViewDataList = new App1Create();
//If application needs to be initiated
var Settings = { some settings };
MainApp.ViewDataList.Config.Init(Settings);
A simple example of one way of creating "multiple independent instances of SubAppA including all its sub modules", where the modules are defined in multiple files:
// test.js
import { MainApp } from './mainApp.js';
import { SubApp } from './subApp.js';
MainApp.SubAppA = new SubApp();
console.log(MainApp.SubAppA.Config.A()); // 1
MainApp.SubAppB = new SubApp();
console.log(MainApp.SubAppB.Config.B()); // -1
// subApp.js
import { config } from './config.js';
import { getData } from './getData.js';
export function SubApp() {
this.Config = config();
this.GetData = getData();
}
// config.js
export function config() {
let counter = 0;
function A() { return ++counter };
function B() { return --counter };
return {
A: A,
B: B
}
}
As a single file:
const MainApp = {};
function SubApp() {
this.Config = config();
this.GetData = getData();
}
function config() {
let counter = 0;
function A() { return ++counter };
function B() { return --counter };
return {
A: A,
B: B
}
}
function getData() {
let counter = 0;
function A() { return ++counter };
function B() { return --counter };
return {
A: A,
B: B
}
}
MainApp.SubAppA = new SubApp();
console.log(MainApp.SubAppA.Config.A()); // 1
console.log(MainApp.SubAppA.GetData.A()); // 1
console.log(MainApp.SubAppA.Config.B()); // 0
MainApp.SubAppB = new SubApp();
console.log(MainApp.SubAppB.Config.B()); // -1
console.log(MainApp.SubAppB.GetData.B()); // -1
console.log(MainApp.SubAppB.Config.A()); // 0
The important difference with your own code is that I have replaced the Immediately-Invoked Function Expressions (IIFE) with normal functions that create closures every time a SubApp is created.
Added in response to your edit:
For the code you added in your edit to work, you need to make sure that you pass a reference to the parent object when you create a new ManageData object:
$S.AS.ManageData = function (owner) {
function StoreData (Data) {
owner.DataStore.SetVar(Data);
};
function DisplayData () {
var SomeVar = owner.DataStore.GetVar();
console.log(SomeVar);
};
return {
StoreData : StoreData,
DisplayData : DisplayData
}
};
// ...
MainApp.S.AS = function () {
this.DataStore = $S.AS.DataStore();
this.ManageData = $S.AS.ManageData(this);
};
I encourage you to use ES modules to structure your code and avoid naming collisions. A single file can be created from a module bundler such as roll-up.js.

Javascript namespacing and OO organization

I have my javascript code as follow:
$(document).ready(function () {
//call of global functions
globalFunction1();
globalFunction2(); //create a new object inside
globalFunction3();
}
function globalFunction1() {
// do something directly with jquery selectors
var testObj1 = new object1($('#tree')); // this is called later in the function
testObj.doSomething();
}
function globalFunction2() {
// do other things
}
function globalFunction3() {
// do something directly with jquery selectors
}
//creating an object in js
var object1 = (function () {
var tree;
function object1($tree) {
tree = $tree;
});
}
object1.prototype.doSomething = function () {
.....
};
return fancyStructure;
})();
Normally I have more global functions and if possible I always try to create objects using the new keyword (as in Java or C#)
Now, I am asked to provide namespacing in order to avoid function conflict problems. Thing is I am not sure how to achieve that giving my current code and knowing that I need to keep the code Object Oriented.
Hence, I am wondering if there is a way to add some namespacing effisciently. Any suggestion will do as long as it is along the lines of adding a namespace.
Just put your functions into an Object:
var mynamespace = {
globalFunction1 : function() {
// do something directly with jquery selectors
var testObj1 = new object1($('#tree')); // this is called later in the function
testObj.doSomething();
},
globalFunction2 : function() {
// do other things
},
globalFunction3 : function() {
// do something directly with jquery selectors
}
}
and call the functions with
mynamespace.globalFunction1();
Or you could just define your namespace
mynamespace = {};
And later add the the functions with
mynamespace.globalFunction1 = function() {
//do something
};
Use objects as containers for your functions. This is the standard approach of code structuring in JS.
var namespace1 = {
func1: function() {},
func2: function() {},
}
var namespace2 = {
func1: function() {},
func2: function() {},
}
namespace1.func2();
You can store your OOP code in this namespaces:
var namespace3 = {
someObj: function() {},
create: function() { return new this.someObj(); },
}
namespace3.someObj.prototype = {
count: 15,
someFunc() {}
}
And you can easily extend them:
namespace3.anotherObj = function () {}
Edit
Regarding your example:
var fancyStructureWrapped = (function () {
var tree;
function fancyStructure($tree) {
tree = $tree;
});
fancyStructure.prototype.doSomething = function () {
.....
};
return fancyStructure;
})();
// add it to some namespace
someNamespace.fancyStructure = fancyStructureWrapped;
//create an instance
var fs = new someNamespace.fancyStructure();
//and use it
fs.doSomething();
If you're looking for a general approach to managing a growing JavaScript codebase, check out RequireJS and/or Browserify. Both are libraries that allow dividing your code up into modular bits (ie. AMD or CommonJS modules) and then referencing/importing between them. They include tooling for bundling these files into a single JS file when it's time to deploy a production build too.

Where to insert an internal (utility) object with a compatible RequireJS/AMD JavaScript library

Maybe the title is not quite useful to understand what is the problem but I'll try to explain in a clear way what I would achieve.
Following Jeremy Kahn template (you can found it at GitHub) I'm creating a library that is compatible with RequireJS and AMD.
The library looks like the following (skipped code for brevity).
;(function(global, undefined) {
var Fn = Function, GLOBAL = new Fn('return this')();
function initLSKitCore(context, _) {
'use strict';
// private vars here...
var LSKit = context.LSKit = function(options) {
this.groups = [];
return this;
};
/**
* Add a new Group
*/
LSKit.prototype.addGroup = function(groupId) {
// implementation here...
};
// other prototype methods...
}
var initLSKit = function(context, deps) {
var context = deps ? {} : global;
var _ = (deps && deps.underscore) ? deps.underscore : context._;
initLSKitCore(context, _);
// other modules here...
return context.LSKit;
};
if (typeof define === 'function' && define.amd) {
define(["underscore"], function (Underscore) {
var underscoreSupportsAMD = (Underscore != null);
// Some versions of Underscore.js support AMD, others don't.
// If not, use the `_` global.
var deps = { underscore: underscoreSupportsAMD ? Underscore : _ };
var SLKit = initLSKit({}, deps);
return SLKit;
});
} else {
initLSKit(this);
}
}(this));
The groups array enables to store, retrieve or get Group objects defined like this.
function Group(identifier, name){
this.identifier = identifier;
this.name = name;
this.internalList = [];
};
Based on that my actual requirement is the following. I would like to use Group as an internal class (I know the term is not correct since it's actually an internal object). So, where is the right place to insert the second snippet (i.e. Group constructor) in my library?
Following your template, you'd just need to inject it in the initLSkit method
if (typeof define === 'function' && define.amd) {
define(["underscore", "lib/group"], function (Underscore, Group) {
var underscoreSupportsAMD = (Underscore != null);
// Some versions of Underscore.js support AMD, others don't.
// If not, use the `_` global.
var deps = { underscore: underscoreSupportsAMD ? Underscore : _, Group: Group };
var SLKit = initLSKit({}, deps);
return SLKit;
});
} else {
initLSKit(this, { Group: global.Group });
}
I believe it is always better to inject your dependencies. So I'd inject underscore too when using the global context. Adding dependency resolution logic inside the initLSKit is just noise inside your business logic (Concerns separation FTW).
Without AMD loading, you can also declare it locally to your module like this:
;(function(global, undefined) {
var Fn = Function, GLOBAL = new Fn('return this')();
// Just create it here, it'll be available inside your module
// and won't be reachable from outside the module (private).
var Group = function() {};
// etc...

How to combine prototypes from closed functions?

Having a project where I have speed coded up some core functionality I would like to split it up into modules. My struggle now is how to combine prototypes from one to the next. My idea is something like this:
(function (window) {
/* Code for base module with core functions. */
function CORE () {
}
window.CORE = CORE; /* I use different naming in real code ... */
})(window);
(function (CORE) {
/* Code for module with extending functionality. */
function MODULE1 () {
}
CORE.MODULE1 = MODULE1;
})(window.CORE);
I use an approach for creation as something like:
(function (window) {
var Core = function (options) {
return new Core.prototype.init(options);
}
Core.prototype = {
init : function (options) {
this.a = options.a;
return this;
}
}
Core.prototype.init.prototype = Core.prototype;
Core.prototype.init.prototype.fun1 = function () { }
Core.prototype.init.prototype.fun2 = function () { }
...
window.Core = Core; /* Optionally = Core.init */
})(window);
And then a module like:
(function (Core) {
var Module1 = Core.Module1 = function (options) {
return new Module1.prototype.build(options);
}
Module1.prototype = {
build : function (options) {
this.a = options.a;
return this;
}
}
Module1.prototype.build.prototype = Module1.prototype;
Module1.prototype.build.prototype.fun1 = function () { }
Module1.prototype.build.prototype.fun2 = function () { }
...
Core.Module1 = Module1;
Core.Module1_XO = Module1.prototype.build;
})(window.Core);
Now a print of toString() of Core, Core.Module1 and Core.Module1_XO all yield their respective code. But there is no binding as in:
If I say:
var obj = Core({...}); , OK.
obj.Module1({...}), Fail. Object #<Object> has no method Module1
new obj.Module1_XO({...}), Fail. undefined is not a function
Core.Module1({...}), OK, but looses prototypes from Core.
new Core.Module1_XO({...}), OK, but looses prototypes from Core.
...
One way that seem to work is by updating Core by a bind function as in:
var obj = Core({...});
var mod1 = Core.Module1({...}, obj); <-- pass obj
// In Module1 constructor:
build : function (options, ref) {
this.a = options.a;
ref.bind("Module1", this);
}
// And In Core:
Core.prototype.bind(which, what) {
this[which] = what;
}
Question is how I can update Core with Module without this hack. Why doesn't Core become updated by:
window.Core.Module1 = Module1;
Is it hidden from Core?
I have also tried to bind in outer scope of module as in:
(function (Core) {
/* ... code ... for Mudule1 */
Core.bind("Module1", Module1);
}(window.Core);
But this fails as well. Core does not get updated with methods from Module.
Here is a scramble of a fiddle I have messed with, (Note that the printed text is in reverse (prepended) not appended such as newest on top.). It is not the most tidy code, and It is in midts of edits. (I try new approaches frequently.)
What you're doing right now is problematic for several reasons:
You're adding a module to the constructor (type) and not the objects.
Global state here - everyone gets one Module1.
My suggestion would be using a generic version of the builder pattern (or even a mediator).
Here is what it might look like.
Core = (function Core(){
var modules = [];
return {
setModule : function(name,value){
modules.push({name:name,value:value});
},
build : function(options){
this.a = options.a;
// now let's add all modules
modules.forEach(function(module){
this[module.name] = new module.value();
});
}
};
});
Usage would be something like:
var app = new Core.build({a:"foo"});
app.a;//"foo"
If you want to add a module it'd be something like
function Module1(){
this.name = "Zimbalabim";
}
Core.setModule("Module1",Module1);
var app = new Core.build({a:"Bar"});
app.Module1.name;//"Zimbalabim"
app.a;//"Bar"
Or course, a more generic architecture would allow creating different apps with different architectures (with dependency injection containers probably) but let's not go that far yet :)

How do you namespace objects in the Revealing Prototype Pattern?

I've been using the Revealing Module pattern and have several namespaces.
Example:
// here's the namespace setup
var myProject= myProject|| {};
var myProject.models= myProject.models || {};
myProject.models.MyModel= function(){
var someMethod = function(){
// do something
};
return{
SomeMethod = someMethod
};
}
I'm moving to the Revealing Prototype Pattern to gain some memory usage improvements and so I can decorate the object another function. How do I keep it in my myProject.models namespace?
This gives my JavaScript errors:
var myProject.models.MyModel= function(){
// properties here
};
myProject.models.MyModel.prototype = (function(){
// methods here
var someMethod = function(){
// do something
};
return{
SomeMethod = someMethod
};
}());
You have various syntax errors.
myProject = window.myProject|| {};
myProject.models = myProject.models || {};
myProject.models.MyModel = (function () {
//declare a constructor function
function MyModel() {
}
//declare a function that will be publicly available on each MyModel instances
MyModel.prototype.someFunction = function () {
//call the private function from within the public one
//note: you have to be careful here since the context object (this) will be
//window inside somePrivateFunction
somePrivateFunction();
//call the private function and set the context object to the current model instance
//somePrivateFunction.call(this);
};
//declare a private function
function somePrivateFunction() {
}
return MyModel; //return the model constructor
})();
Now you can use your model like:
var m = new myProject.models.MyModel();
m.someFunction();
var myProject = myProject || {};
^^^
You are using a var statement here to declare the global myProject variable (if it hasn't been already), so that it will not throw Undefined variable exceptions. (Also you initialise it to an empty object if it had now value)
var myProject.models= myProject.models || {};
In here, you are assigning the models property to the object from above. The var keyword is out of place here; remove it and it will work.
With myProject.models.MyModel = … you did it right in the upper snippet and wrong in the second one; I'm not sure which you were trying to use. The revealing prototype pattern should look like this:
var myProject = myProject || {};
myProject.models = myProject.models || {};
myProject.models.MyModel = (function(){
function MyModel() {
// instance properties here
}
function someMethod(){
// do something
}
MyModel.prototype.SomeMethod = someMethod;
// ^ lowercase that?
return MyModel;
})();

Categories