Javascript Namespace manager

K

Kevin Newman

I've been toying with a namespace manager, and wanted to get some input.
So what do you think?


if (typeof com == 'undefined') var com = {};
if (!com.unFocus) com.unFocus = {};

com.unFocus.Namespaces = new function() {
this.register = function(namespace) {
namespace = namespace.split('.');

// do first one (doesn't need eval)
if (!window[namespace[0]]) window[namespace[0]] = {};

// do the rest
for (var i = 1; namespace.length > i; i++) {
$namespace = namespace[i-1] + '.' + namespace;
eval( 'if(!window.' + namespace + ')window.' +
namespace + '={};' );
}
}
}


Namespaces are added like this:

com.unFocus.Namespaces.register('com.unFocus.util');


I may also add an import method that would add all of the enumerable
elements of a namespace to the global space (window.xx), and possibly
and export method that would remove the imported namespace elements (I'd
consider a different name for that one).

BTW, has anyone created anything like this already? I wouldn't want to
re-invent the wheel.

Thanks! :)
 
R

Richard Cornford

Kevin said:
I've been toying with a namespace manager, and wanted to
get some input. So what do you think?

You haven't actually said what it is you think this "namespace manager"
is for.
if (typeof com == 'undefined') var com = {};
if (!com.unFocus) com.unFocus = {};

com.unFocus.Namespaces = new function() {
this.register = function(namespace) {

That is very odd. If you want to create an object with a method why
not:-

com.unFocus.Namespaces = {
register:function(namespace){
namespace = namespace.split('.');
...
}
};

- rather than use a function expression as a one-off constructor?
namespace = namespace.split('.');

// do first one (doesn't need eval)
if (!window[namespace[0]]) window[namespace[0]] = {};

Stuffing references to objects into the global namespace using arbitrary
names does not seem like a good idea at all. The potential for
accidental naming conflicts seems considerable.
// do the rest
for (var i = 1; namespace.length > i; i++) {
$namespace = namespace[i-1] + '.' + namespace;


Why are you using a global variable for - $namespace -? But it looks
like that is not the correct variable name anyway.
eval( 'if(!window.' + namespace + ')window.' +
namespace + '={};' );


There is no need for - eval - at all here:-

com.unFocus.Namespaces = {
register:function(namespace){
var tempObj, baseObject = window;
var length, index = 0;
namespace = namespace.split('.');
if((length = namespace.length)){
do{
if(!(tempObj = baseObject[namespace[index]])){
tempObj = baseObject[namespace[index]] = {};
}
baseObject = tempObj;
}while(++index < length);
}
}
};

BTW, has anyone created anything like this already? I
wouldn't want to re-invent the wheel.

With javascript's potential for having private scopes (and so
effectively private namespaces) it seems more likely that this is trying
to solve the wrong problem. And quite a convoluted way of going about
it.

Richard.
 
K

Kevin Newman

Richard said:
You haven't actually said what it is you think this "namespace manager"
is for.

Well I saw a script that used objects to simulate namespaces in this
way, and thought it looked like a good idea
(http://blog.deconcept.com/flashobject/). I would use these "namespaces"
to organize some scripts that I'm working on to keep them from
cluttering up the global space. I am really still learning javascript
and programming in general (including namespaces in actionscript 2.0 and
c# and general OOP in PHP, javascript, etc.) and am still trying to
figure out the best way to organize things to keep them clean and
understandable. Namespaces seem like a good way to do that, so I figured
I would attempt to simulate them in javascript.

This register method would be used as a simpler way to do this:

if (typeof com == 'undefined') var com = {};
if (!com.unFocus) com.unFocus = {};

etc.

I was also toying with the idea of adding import and export (or
removeNamespaceItems or something) methods so that someone could import
a particular namespace into the current scope. I suppose since in
javascript, functions have access to parent scopes, this would be kinda
silly...still those functions would have merit to make accessing
namespaces created by this class simpler - though only if this way of
simulating namespaces has merit ;-).
That is very odd. If you want to create an object with a method why
not:-

com.unFocus.Namespaces = {
register:function(namespace){
namespace = namespace.split('.');
...
}
};

- rather than use a function expression as a one-off constructor?

good point.
namespace = namespace.split('.');

// do first one (doesn't need eval)
if (!window[namespace[0]]) window[namespace[0]] = {};

Stuffing references to objects into the global namespace using arbitrary
names does not seem like a good idea at all. The potential for
accidental naming conflicts seems considerable.

Well this actually keeps all of the namespace objects contained under
the base namespace (I use com.unFocus in all of mine for example). So
the only object in the global namespace is com. I figure it is up to the
namespace implementor to figure out what references they are stuffing
into the global namespace.

If I didn't understand your comment, please re-explain? :)
// do the rest
for (var i = 1; namespace.length > i; i++) {
$namespace = namespace[i-1] + '.' + namespace;


Why are you using a global variable for - $namespace -? But it looks
like that is not the correct variable name anyway.


Wrong variable name. Apologies.

There is no need for - eval - at all here:-

com.unFocus.Namespaces = {
register:function(namespace){
var tempObj, baseObject = window;
var length, index = 0;
namespace = namespace.split('.');
if((length = namespace.length)){
do{
if(!(tempObj = baseObject[namespace[index]])){
tempObj = baseObject[namespace[index]] = {};
}
baseObject = tempObj;
}while(++index < length);
}
}
};

I was hoping someone could help me out of that eval! :-D
Very interesting solution btw. Thank you.

With javascript's potential for having private scopes (and so
effectively private namespaces) it seems more likely that this is trying
to solve the wrong problem. And quite a convoluted way of going about
it.

Well I guess it is like trying to make javascript behave like other
languages. Do you have any pointers for how better to organize a lot of
classes (and to distribute them without worrying about naming collisions)?

Thanks!

Kevin N.
 
R

Richard Cornford

Kevin said:
Well I saw a script that used objects to simulate namespaces in this
way, and thought it looked like a good idea
(http://blog.deconcept.com/flashobject/). I would use these
"namespaces" to organize some scripts that I'm working on to keep
them from
cluttering up the global space. I am really still learning javascript
and programming in general (including namespaces in actionscript 2.0
and c# and general OOP in PHP, javascript, etc.) and am still trying
to figure out the best way to organize things to keep them clean and
understandable. Namespaces seem like a good way to do that, so I
figured I would attempt to simulate them in javascript.

This register method would be used as a simpler way
to do this:

if (typeof com == 'undefined') var com = {};
if (!com.unFocus) com.unFocus = {};

etc.

A simpler way of doing that is:-

var com = {unfocus:{}};

// do first one (doesn't need eval)
if (!window[namespace[0]]) window[namespace[0]] = {};

Stuffing references to objects into the global namespace
using arbitrary names does not seem like a good idea at
all. The potential for accidental naming conflicts seems
considerable.

Well this actually keeps all of the namespace objects
contained under the base namespace (I use com.unFocus
in all of mine for example).

If you always use the same single object in the global namespace there
is no need to start the assignment process with - window -, but if you
do you are allowing the creation of named properties of the global
object with arbitrary names.
So the only object in the global namespace is com.

Only if there is no possibility of this code being employed by scripts
with a different namespace.
I figure it is up to the namespace implementor
to figure out what references they are
stuffing into the global namespace.

If you write the code that stuffs the names into the global namespace it
is your responsibility to handle the issues of doing so.

Well I guess it is like trying to make javascript behave
like other languages.

You are only making javascript look like other languages (and then not
that much like them). Javascript is going to behave like javascript, and
all this namespace qualification is just going to bloat the code and
impose a runtime efficiency cost. Which the use of namespaces in
compiled languages the cost of resolving those namespaces will tend to
happen when the source is compiled rather than each and every time any
particular statement is executed.
Do you have any pointers for how better to organize
a lot of classes

The structures in javascript that are most analogous with classes in
class-based languages need only impose (at most) one name on the global
namespace per 'class'.

In a class-based language there is a good chance that a library of
hundreds of packages already exists, alongside any created by the
developers using the language. Thus a class called, for example,
"Document" is likely to occur in a number of packages, and need to be
more qualified in order to distinguish between them. In javascript there
are no libraries/packages distributed with the language, and the
'classes' used in any particular browser scripting context are further
restricted by the need to download the source code, so it is actually a
bad idea to be including anything that is not actually needed in that
context. In any specific context (even a fairly large web application)
it is both unlikely that the number of 'classes' being used would grow
to an unmanageable level (at least if the author understood what they
were doing) and unlikely that two classes would even suggest using the
same name.
(and to distribute them without worrying about naming
collisions)?

In what sense "distribute"?

Richard.
 
K

Kevin Newman

Richard said:
A simpler way of doing that is:-

var com = {unfocus:{}};

That's true, but if someone else already has properties on the com
object, this would overwrite their simulated namespace (like com.deconcept).
// do first one (doesn't need eval)
if (!window[namespace[0]]) window[namespace[0]] = {};
Stuffing references to objects into the global namespace
using arbitrary names does not seem like a good idea at
all. The potential for accidental naming conflicts seems
considerable.
Well this actually keeps all of the namespace objects
contained under the base namespace (I use com.unFocus
in all of mine for example).

If you always use the same single object in the global namespace there
is no need to start the assignment process with - window -, but if you
do you are allowing the creation of named properties of the global
object with arbitrary names.
So the only object in the global namespace is com.

Only if there is no possibility of this code being employed by scripts
with a different namespace.

That's true, but it seemed (to me at least) that languages that have
formal namespace support would have this same type of problem.
If you write the code that stuffs the names into the global namespace it
is your responsibility to handle the issues of doing so.

That's worth considering.
You are only making javascript look like other languages (and then not
that much like them). Javascript is going to behave like javascript, and
all this namespace qualification is just going to bloat the code and
impose a runtime efficiency cost. Which the use of namespaces in
compiled languages the cost of resolving those namespaces will tend to
happen when the source is compiled rather than each and every time any
particular statement is executed.

Getting those term definitions right is important. ;-) You are right, it
does just look like other namespace implementations (sort of) which is
actually what I really meant by behave.
The structures in javascript that are most analogous with classes in
class-based languages need only impose (at most) one name on the global
namespace per 'class'.

In a class-based language there is a good chance that a library of
hundreds of packages already exists, alongside any created by the
developers using the language. Thus a class called, for example,
"Document" is likely to occur in a number of packages, and need to be
more qualified in order to distinguish between them. In javascript there
are no libraries/packages distributed with the language, and the
'classes' used in any particular browser scripting context are further
restricted by the need to download the source code, so it is actually a
bad idea to be including anything that is not actually needed in that
context. In any specific context (even a fairly large web application)
it is both unlikely that the number of 'classes' being used would grow
to an unmanageable level (at least if the author understood what they
were doing) and unlikely that two classes would even suggest using the
same name.


In what sense "distribute"?

I'm working on a set of scripts that will (hopefully) make it easier to
allow flash (or AJAX) developers to add browser back button support, and
deep links to their projects. I have a bunch of classes, including some
utility classes that I use to make this work. I started without using
this style of namespace, and found that I was coming up with long names
to prevent my Classes from clashing with other projects (names like
unFocusFlashCommunicator). Then I found information about that namespace
technique, and figured that would be a good way to keep my scripts from
clashing with an implementor's script names, without using excessively
long class names (so I'd use com.unFocus.Flash.Communicator). I have
realized though that the names are still long, but it seems better
organization, and it is pretty easy to "import" the classes to the
global space.

I have thought that the script tag is kind of analogous to an import
statement in namespace supporting languages - meaning, only scripts that
have been linked into the current page are actually in the global space
(I think this is what you were getting at). So thinking about it in that
way, organizing them might make more sense, if I just organize my
classes in a namespace style folder hierarchy, then just link them into
the document that needs to call on them.

Maybe that would be a better way to organize classes to take advantage
of javascript's unique strengths, instead of trying to make it look like
other languages, though in some cases, I may still create collections of
useful methods (kind of like static classes I guess).

Thanks Richard.

Kevin N.
 
S

steveH

You'll find the dojo framework makes extensive use of the 'namespace'
idiom you've described above. Why noy have a look at how those guys do
it.
 
R

Richard Cornford

Kevin said:
That's true, but if someone else already has properties
on the com object, this would overwrite their simulated
namespace (like com.deconcept).

Isn't your namespace function a method of an object in this structure?

I'm working on a set of scripts that will (hopefully)
make it easier to allow flash (or AJAX) developers to
add browser back button support,

A rather odd idea as browsers already have a 'back' facility (and
usually several ways of activation it).
and deep links to their projects. I have a bunch of
classes, including some utility classes that I use to
make this work.

What you seem to be describing only seems to require a single public
object, but as usual it is extremely difficult to say anything based on
just a description of code.
I started without using this style of namespace, and
found that I was coming up with long names to prevent my
Classes from clashing with other projects (names like
unFocusFlashCommunicator).

That is a very odd 'class' name (even given a disregard for the
convention of giving 'class' names initial capital letters), it reads
more like a method name. But again it is not that practical to say
anything about code based on a single proposed 'class' name.
Then I found information about that namespace technique,
and figured that would be a good way to keep my scripts
from clashing with an implementor's script names, without
using excessively long class names (so I'd use
com.unFocus.Flash.Communicator).

In principle a 'class' should be named for what it is. So if two
'classes' share the same name they should be the same thing, and one of
them becomes redundant. At least this should be the case for the
'classes' in the global namespace, several 'classes' might want to use,
for example distinct Rectangle' classes', by global 'classes' but the
very fact that those 'classes' are specific to separate global 'classes'
suggests that they should be internal to the global 'class'.

There just isn't a namespace issue in javascript, except as a result of
people not understanding the code that they are using. And if they don't
understand what they are doing they are as likely to screw up a system
trying to impose 'namespaces' as they are to screw up anything else.

I have thought that the script tag is kind of analogous
to an import statement in namespace supporting languages
- meaning, only scripts that have been linked into the
current page are actually in the global space (I think
this is what you were getting at).

No, that was not what I was thinking about. I was thinking about
employing javascript's potential for encapsulation to reduce the impact
on the global namespace to the absolute minimum possible, and so keep
potential naming collisions below a level that can easily be managed by
a human even in the biggest practical client-side systems.

Maybe that would be a better way to organize classes to
take advantage of javascript's unique strengths, instead
of trying to make it look like other languages, though in
some cases, I may still create collections of useful
methods (kind of like static classes I guess).

It is certainly not a good idea to try to imitate other languages when
doing so imposes an overhead on every operation that includes the sue of
it. This is in part because 'namespaces' should not even start to become
an issue until the totality of client-side code becomes very large, but
the more client-side code there is the greater the chances that its
performance will be a significant factor in the viability of end result.

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top