In my project I have several classes that look like this:
"use strict";
var exports = module.exports = {};
var SystemsDAO = require('./dao/systems/SystemsDAO.js');
var aop = require('./dbAOPUtils.js');
var Proxy = require('harmony-proxy');
var sqlite3 = require('sqlite3').verbose();
/* Wraps a SystemServiceObject and passes in a constructed
* DAO object as an argument to specified functions. */
exports.SystemsDAOIntercepter = function(obj) {
let handler = {
get(target, propKey, receiver) {
const origMethod = target[propKey];
return function(...args) {
console.log('systemDAOIntercepter: BEGIN');
// Create a reportsdao object and proxy it through an dbSQLiteConnectionIntercepter
// (So we don't have to create it for every single method)
var systemdao = new SystemsDAO('blah');
var proxSystemDAO = aop.dbSQLiteConnectionIntercepter(systemdao, sqlite3.OPEN_READONLY);
args.push(proxSystemDAO);
console.log('propKey: ' + target[propKey]);
let result = null;
result = origMethod.apply(this, args);
console.log('systemsDAOIntercepter: END');
return result;
};
}
};
return new Proxy(obj, handler);
};
Is it possible to pass in a type for an argument so that I only need a single DAOIntercepter class, and not one for each data access object?
I can see the part where I require() the SystemsDAO working for this by passing the file name, but as for instantiation of that class, I can't really see how it would be possible to do that.
Sure - you can pass classes around like any other variable in javascript.
Note that DAOType is provided and instantiated inside the method, now.
"use strict";
var exports = module.exports = {};
var aop = require('./dbAOPUtils.js');
var Proxy = require('harmony-proxy');
var sqlite3 = require('sqlite3').verbose();
/* Wraps a SystemServiceObject and passes in a constructed
* DAO object as an argument to specified functions. */
exports.makeInterceptor = function(DAOType, obj) {
let handler = {
get(target, propKey, receiver) {
const origMethod = target[propKey];
return function(...args) {
console.log('systemDAOIntercepter: BEGIN');
// Create a reportsdao object and proxy it through an dbSQLiteConnectionIntercepter
// (So we don't have to create it for every single method)
var dao = new DAOType('blah');
var proxSystemDAO = aop.dbSQLiteConnectionIntercepter(dao, sqlite3.OPEN_READONLY);
args.push(proxSystemDAO);
console.log('propKey: ' + target[propKey]);
let result = null;
result = origMethod.apply(this, args);
console.log('makeInterceptor: END');
return result;
};
}
};
return new Proxy(obj, handler);
};
I have to admit that I would (personally) prefer to see the class instantiated externally and injected in through the arguments, however, instead of creating it inline.
I've made a class in my NodeJS app and used module.exports along with a require() statement to bring it into my main server script:
// ./classes/clientCollection.js
module.exports = function ClientCollection() {
this.clients = [];
}
// ./server.js
var ClientCollection = require('./classes/clientCollection.js');
var clientCollection = new ClientCollection();
Now I'd like to add functions onto my class like so:
ClientCollection.prototype.addClient = function() {
console.log("test");
}
However when I do this I get the following error:
ReferenceError: ClientCollection is not defined
How do I properly add functions to a class using prototyping in a NodeJS app?
I think that you need.
function ClientCollection (test) {
this.test = test;
}
ClientCollection.prototype.addClient = function() {
console.log(this.test);
}
module.exports = ClientCollection;
or
function ClientCollection () {
}
ClientCollection.prototype = {
addClient : function(){
console.log("test");
}
}
module.exports = ClientCollection;
For various reasons, this structure:
module.exports = function ClientCollection() {
this.clients = [];
}
does not define the symbol ClientCollection outside of the function itself so you can't refer to it elsewhere in the module to add to the prototype. So, instead, you need to define it outside and then assign it to exports:
function ClientCollection() {
this.clients = [];
}
ClientCollection.prototype.addClient = function() {
// code here
}
module.exports = ClientCollection;
Let's say I have a namespace like that:
var myNamespace = {
foo: function() {
},
bar: function() {
}
};
What is the best way to split this code into files defining foo and bar separately?
I'm not worried about loading time - I'll concatenate it back into one file before deployment.
At the start of each file:
if(myNameSpace === undefined) {
var myNameSpace = {};
}
File 1:
myNamespace.foo = function()...
File 2:
myNamespace.bar = function()...
// File1:
// top level namespace here:
var myNamespace = myNamespace || {};
// File2:
myNamespace.foo = function() {
// some code here...
}
In each file follow this pattern:
(function(nameSpace) {
nameSpace.foo = function() { ... };
})(window.nameSpace = window.nameSpace || {});
This way load ordering is unimportant.
Simple define in seperate files like this:
File 1:
var myNamspace = {};
File 2:
myNamespace.foo = function()...
File 3:
myNamespace.boo = function()...
Just make sure you load the files in the right order.
(function (NS) {
NS.Uber = function Uber() {
this.super = new NS.Super(); // yes, it works!
}; //
}(NS = NS || {}));
// ------------- other file -----------------
(function (NS) {
NS.Super = function Super() {
this.uber = new NS.Uber(); // yes, it will also work!
}; //
}(NS = NS || {}));
// -------------- application code ------------
var uber = new NS.Uber();
console.log(uber.super);
var super = new NS.Super();
console.log(super.uber);
What is the proper way to declare a namespace? I've just read "Developing Large Web Applications" and the author suggests using:
if (!window.YourNamespace) {
YourNamespace = {};
}
seems easy enough.. but I see all the javascript libraries for declaring namespaces and alternate methods. Isn't there a standard way to do this? Any problems with the above?
I've seen this convention used several places.
window.YourNamespace = window.YourNamespace || {};
The mentioned namespace-declarating-way by book author is indeed quite good one. But when you need to repeat it in several files and the namespace has several subnamespaces, it can get quite tedious:
if (!window.Foo) {
Foo = {};
}
if (!window.Foo.Bar) {
Foo.Bar = {};
}
if (!window.Foo.Bar.Baz) {
Foo.Bar.Baz = {};
}
etc...
Instead you should write a simple function that takes care of declaring the namespaces for you:
function namespace(ns) {
var parts = ns.split(/\./);
var obj = window;
for (var i=0; i<parts.length; i++) {
var p = parts[i];
if (!obj[p]) {
obj[p] = {};
}
obj = obj[p];
}
}
Now you can declare the whole nested namespace with just one line:
namespace("Foo.Bar.Baz");
In ExtJS framework this is basically what Ext.ns() function does. I don't really know about other libraries.
var Utils = {
namespace : function(name) {
return window[name] = window[name] || {};
}
};
or if you prefer your way use:
if (typeof window.YourNamespace === 'undefined') {
YourNamespace = {};
}
There is no standard way as you'll see between frameworks but they do go beyond the basics so that for example X.Y.Z, it will create all objects in that chain if they don't already exist.
bob.js handles namespaces like this:
bob.ns.setNs('YourNamespace', {
/*define your members here. e.g.:*/
method1: function () { /*...*/ }
});
// now, merge another, sub-namespace.
bob.ns.setNs('YourNamespace.YourSubNamespace', {
method2 function () { /*...*/ }
});
//call methods:
YourNamespace.method1();
YourNamespace.YourSubNamespace.method2();
Automating namespaces declaration in javascript is very simple as you can see:
var namespace = function(str, root) {
var chunks = str.split('.');
if(!root)
root = window;
var current = root;
for(var i = 0; i < chunks.length; i++) {
if (!current.hasOwnProperty(chunks[i]))
current[chunks[i]] = {};
current = current[chunks[i]];
}
return current;
};
// ----- USAGE ------
namespace('ivar.util.array');
ivar.util.array.foo = 'bar';
alert(ivar.util.array.foo);
namespace('string', ivar.util);
ivar.util.string.foo = 'baz';
alert(ivar.util.string.foo);
Try it out: http://jsfiddle.net/stamat/Kb5xY/
Blog post: http://stamat.wordpress.com/2013/04/12/javascript-elegant-namespace-declaration/
Some example of namespace function:
namespace = function(ns){
arr = ns.split(".")
parent = window
var temp
while( ( temp = arr.shift()) !== undefined){
parent[temp] = parent[temp] || {}
parent = parent[temp]
}
}
You can then use it as:
namespace("your.own.namespace")
your.own.namespace.Car= function () {
this.speed = 30;
}
I created a javascript class as follow:
var MyClass = (function() {
function myprivate(param) {
console.log(param);
}
return {
MyPublic : function(param) {
myprivate(param);
}
};
})();
MyClass.MyPublic("hello");
The code above is working, but my question is, how if I want to introduce namespace to that class.
Basically I want to be able to call the class like this:
Namespace.MyClass.MyPublic("Hello World");
If I added Namespace.MyClass, it'll throw error "Syntax Error".
I did try to add "window.Namespace = {}" and it doesn't work either.
Thanks.. :)
Usually I'd recommend doing this (assuming Namespace is not defined elsewhere):
var Namespace = {};
Namespace.MyClass = (function () {
// ...
}());
A more flexible, but more complex, approach:
var Namespace = (function (Namespace) {
Namespace.MyClass = function() {
var privateMember = "private";
function myPrivateMethod(param) {
alert(param || privateMember);
};
MyClass.MyPublicMember = "public";
MyClass.MyPublicMethod = function (param) {
myPrivateMethod(param);
};
}
return Namespace
}(Namespace || {}));
This builds Namespace.MyClass as above, but doesn't rely on Namespace already existing. It will declare and create it if it does not already exist. This also lets you load multiple members of Namespace in parallel in different files, loading order will not matter.
For more: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
YUI has a nice method for declaring namespaces
if (!YAHOO) {
var YAHOO = {};
}
YAHOO.namespace = function () {
var a = arguments,
o = null,
i, j, d;
for (i = 0; i < a.length; i = i + 1) {
d = ("" + a[i]).split(".");
o = YAHOO;
for (j = (d[0] == "YAHOO") ? 1 : 0; j < d.length; j = j + 1) {
o[d[j]] = o[d[j]] || {};
o = o[d[j]];
}
}
return o;
}
Place it above any function that you want to namespace like this:
YAHOO.namespace("MyNamespace.UI.Controls")
MyNamespace.UI.Controls.MyClass = function(){};
MyNamespace.UI.Controls.MyClass.prototype.someFunction = function(){};
This method is actually stand-alone and can easily be adapted to your application. Just find and replace "YAHOO" with your application's base namespace and you'll have something like MyOrg.namespace. The nice thing with this method is that you can declare namespaces at any depth without having to create object arrays in between, like for "UI" or "Controls"
A succinct way to do what you're asking is create "Namespace" as an object literal like this:
var Namespace = {
MyClass : (function() {
... rest of your module
})();
};
This could cause conflicts if you wanted to attach other details to Namespace in other files, but you could get around that by always creating Namespace first, then setting members explicitly.
Checkout the namespace library, it is very lightweight and easy to implement.
(function(){
namespace("MyClass", MyPublic);
function MyPublic(x){
return x+1;
}
})();
It supports automatically nesting as well
namespace("MyClass.SubClass.LowerClass", ....)
Would generate the necessary object hierarchy, if MyClass, SubClass did not already exist.
bob.js has nice syntax to define JavaScript namespace:
bob.ns.setNs('myApp.myMethods', {
method1: function() {
console.log('This is method 1');
},
method2: function() {
console.log('This is method 2');
}
});
//call method1.
myApp.myMethods.method1();
//call method2.
myApp.myMethods.method2();
(function($){
var Namespace =
{
Register : function(_Name)
{
var chk = false;
var cob = "";
var spc = _Name.split(".");
for(var i = 0; i<spc.length; i++)
{
if(cob!=""){cob+=".";}
cob+=spc[i];
chk = this.Exists(cob);
if(!chk){this.Create(cob);}
}
if(chk){ throw "Namespace: " + _Name + " is already defined."; }
},
Create : function(_Src)
{
eval("window." + _Src + " = new Object();");
},
Exists : function(_Src)
{
eval("var NE = false; try{if(" + _Src + "){NE = true;}else{NE = false;}}catch(err){NE=false;}");
return NE;
}
}
Namespace.Register("Campus.UI.Popup")
Campus.UI.Popup=function(){
defaults={
action:'',
ispartialaction:'',
customcallback:'',
confirmaction:'',
controltoupdateid:'',
width:500,
title:'',
onsubmit:function(id){
var popupid=id+"_popupholder";
if(this.ispartialaction){
$.ajax({
url:this.action,
type:"Get",
context:this,
success:function(data){
$('#'+id).parents('body').find('form').append("<div id'"+popupid+"'></div>");
var ajaxContext=this;
$("#"+popupid).dialog({
autoopen:false,
model:true,
width:this.width,
title:this.title,
buttons:{
"Confirm":function(){
if(ajaxContext.customcallback==''){
var popupform=$(this).find("form");
if(popupform.isValid()){
$.post(ajaxContext.confirmaction,popupform.serialize(),function(d){
if(d!='')
{
$.each(d.Data,function(i,j){
switch(j.Operation)
{
case 1:
if($('#'+j.ControlClientID).is("select"))
{
$('#'+j.ControlClientID).val(j.Value);
$('#'+j.ControlClientID).change();
}
else if($('input[name="'+j.ControlClientID+'"]').length>0)
{
$('input[name="'+j.ControlClientID+'"][value="'+j.Value+'"]').prop("checked",true);
}
break;
case 2:
if($('#'+j.ControlClientID).is("select"))
{
$('#'+j.ControlClientID).append("<option selected='selected' value=\""+j.Value+"\">"+j.Text+"</option>");
}
else
{
var len=$('input[name="'+j.ControlClientID+'"]').length;
$('#'+j.ControlClientID+"list").append('<li><input type="checkbox" name="'+j.ControlClientID+'" value="'+j.Value+'" id="ae'+j.ControlClientID+len+'"/><label for "ae'+j.ControlClientID+len+'">'+j.Text+'</label>');
}
break;
case 0:
$('#'+j.ControlClientID).val(j.Value);
breakl
default:break;
}
});
popupform.parent().dialog("destroy").remove();
$("#"+ajaxContext.controltoupdateid).change();
}
});
}
}
else
{
executeByFunctionName(ajaxContext.customcallback,window,new Array());
}
},
"Cancel":function(){
$(this).dialog("close");
}
}
});
$("#"+popupid).dialog("open");
$("#"+popupid).empty().append(data);
},
error:function(e)
{
alert(e);
}
});
}
else
{
var frm=document.createElement("form");
frm.id="CampusForm";
frm.name="CampusForm";
frm.action=this.action;
frm.method="post";
var arr=$($("#"+id).closest("body").find("form")).serializeArray();
$.each(arr,function(i,j){
var hidd=document.createElement("input");
hidd.type="hidden";
hidd.name=j.name;
hidd.value=j.value;
frm.appendChild(hidd);});
document.appendChild(frm);
frm.submit();
}
}
},
clicksubmit=function(){
var opts=$(this).data("CampusPopup");
opts.onsubmit($(this).attr("id"));
return false;
};
return
{
init:function(opt){
var opts=$.extend({},defaults,opt||{});
$(this).data('CampusPopup',opts);
$(this).bind("click",clicksubmit);
}};
}();
$.extend({CampusPopup:Campus.UI.Popup.init});
})(jQuery)
Automating namespaces declaration in javascript is very simple as you can see:
var namespace = function(str, root) {
var chunks = str.split('.');
if(!root)
root = window;
var current = root;
for(var i = 0; i < chunks.length; i++) {
if (!current.hasOwnProperty(chunks[i]))
current[chunks[i]] = {};
current = current[chunks[i]];
}
return current;
};
// ----- USAGE ------
namespace('ivar.util.array');
ivar.util.array.foo = 'bar';
alert(ivar.util.array.foo);
namespace('string', ivar.util);
ivar.util.string.foo = 'baz';
alert(ivar.util.string.foo);
Try it out: http://jsfiddle.net/stamat/Kb5xY/
Blog post: http://stamat.wordpress.com/2013/04/12/javascript-elegant-namespace-declaration/
This is the design pattern I use which allows for nested namespaces as well as adding to the namespace later (even from a separate JS file) so you don't pollute the global namespace:
Example: JsFiddle
(function ($, MyObject, undefined) {
MyObject.publicFunction = function () {
console.log("public");
};
var privateFunction = function () {
console.log("private");
};
var privateNumber = 0;
MyObject.getNumber = function () {
this.publicFunction();
privateFunction();
privateNumber++;
console.log(privateNumber);
};
// Nested namespace
MyObject.nested = MyObject.nested || {};
MyObject.nested.test = function (text) {
console.log(text);
};
}(jQuery, window.MyObject = window.MyObject || {}));
// Try it
MyObject.getNumber();
MyObject.nested.test('Nested');
Here is how to add to MyObject from another JavaScript file:
(function ($, MyObject, undefined) {
MyObject.newFunction = function () {
console.log("Added");
};
}(jQuery, window.MyObject = window.MyObject || {}));
// Pass `jQuery` to prevent conflicts and `MyObject` so it can be added to, instead of overwritten
This resource helped me learn all about the different JS design patterns: http://addyosmani.com/resources/essentialjsdesignpatterns/book/
To create new JavaScript namespaces (like Math), I personally define the following base class that can be extended, but not instantiated:
class Namespace {
constructor() { throw TypeError("cannot instantiate a namespace") }
}
Subclasses will inherit constructor or override it with a method that calls super, so instantiation results in a TypeError either way.
The actual namespaces are defined by extending Namespace with any number of static properties (which can reference one another):
class ASCII extends Namespace {
static whitespace = "\t\n\r\v ";
static digits = "0123456789";
static uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static lowers = ASCII.uppers.toLowerCase();
static alphas = ASCII.uppers + ASCII.lowers;
static alphanumerics = ASCII.alphas + ASCII.digits;
}
const isDigital = candidate => ASCII.digits.includes(candidate);
The example use a bunch of string constants, but a namespace can contain any types of value, including functions (defined as static methods).