2

Say i have this function that dynamically creates my namespace for me when I just pass it a string, (I'm pretty sure basically what YUI JS library does):

MyObj.namespace('fn.method.name');

would result in

MyObj.fn.method.name = {}

being created - all three levels being equivalent to an empty object.

Now, what I want to do, though, is make the last level, in this case name, set to a function, but without having to redeclare the newly created object.
So instead of doing this:

function fnName() { /* some code here */ }
MyObj.namespace('fn.method.name');
MyObj.fn.method.name = new fnName();

i want to call something like:

MyObj.add('fn.method.name', fnName);

And internally, the add method would programmatically instantiate the passed in function:

MyObj.fn.method.name = new fnName()

In the way I have it implemented, I can create the namespace object and set it to an empty object, however, when I try to instantiate a passed in function and associate that namespace with the passed in function, it never gets added to the namespace. Instead, an empty object is always returned. Any ideas?

edit: Here is the namespace method. this is attached to the base object as a JSON object, so please ignore the formatting:

namespace: function (ns) {
    var _ns = ns.split('.'), 
        i = 0, nsLen = _ns.length,
        root = this;
    if (_ns[0] === gNS) {
        _ns.shift();
            nsLen = _ns.length;
        }
        for (i = 0; i < nsLen; i++) { 
            // create a property if it doesn't exist 
            var newNs = _ns[i];
            if (typeof root[newNs] === "undefined") {
                root[newNs] = {};
            }
            root = root[newNs];
        }
        return root;
    }

edit2 - removed the passed in fn argument

6
  • Where do you got the namespace() function from? Commented Jan 11, 2011 at 14:49
  • 1
    You are contradicting yourself. First you say you want to set name to a function, but then you say you want to set it to the result of new fnName(). Commented Jan 11, 2011 at 14:51
  • 1
    Obviously, "all three levels" cannot be empty objects: the fn object contains the method property, and the method object contains the name property. Commented Jan 11, 2011 at 14:53
  • An API like that would be a pretty bad idea; how is the framework supposed to know what arguments to pass to the constructor? Why not just instantiate whatever you want, and have the namespace initializer just do a simple assignment? Commented Jan 11, 2011 at 15:03
  • 1
    It'd probably help for you to post the namespace function so that people here could edit it to answer your question. Commented Jan 11, 2011 at 16:00

3 Answers 3

1

Were you looking for something like this:

var root = {};

function create(ns, fn) {
   var nsArray = ns.split(/\./);
   var currentNode = root;

   while(nsArray.length > 1) {
      var newNS = nsArray.shift();

      if(typeof currentNode[newNS] === "undefined") {
         currentNode[newNS] = {};
      }

      currentNode = currentNode[newNS];
   }

   if(fn) {
      currentNode[nsArray.shift()] = fn;
   }

   else {
      currentNode[nsArray.shift()] = {};
   }
}

Then:

create("a.b.c");

console.log(root.a);
console.log(root.a.b);
console.log(root.a.b.c);

Gives:

Object { b={...}}
Object { c={...}}
Object {}

And:

create("d.e.f", function() { console.log("o hai"); });

console.log(root.d);
console.log(root.d.e);
console.log(root.d.e.f);

Gives:

Object { e={...}}
Object {}
function()

Calling the function you defined:

root.d.e.f();

Gives:

o hai
Sign up to request clarification or add additional context in comments.

2 Comments

thanks, Vivin. had to change my script around to get it to work, but seems to work great!
@dtan No problem, glad to help! I wrote it pretty quickly. But you should be able to make it work similarly if you set currentNode to this.
0

Well you haven't given the namespace function but your add function could look something like this:

MyObj.add = function (namespace, value) {

    var names = namespace.split('.'), current = this, name;

    while (names.length > 1) {

        name = names.shift();
        current[name] = {};
        current = current[name];

    }

    current[names[0]] = value;

};

This code assigns the value given to the last part of the namespace. You could modify it to current[names[0] = new value(); if you want the object constructed by the passed in function (and you are assuming the constructor function takes no arguments).

1 Comment

i think this will work, david, but Vivin's does a check for whether or not the object exists already.
0
function ns() {
    var root = window;

    for (var i = 0; i < arguments.length; i++) {
        var arr = arguments[i].split(/\./);

        for (var j = 0; j < arr.length; j++) {
            var item = arr[j];

            if (typeof item !== 'string') {
                root = item;
            } 
            else {
                if (!root[item]) {
                    root[item] = {};
                }
                root = root[item];
            }
        }
        root = window;
    }
}

then you can create using

ns('fn.method.name');

or

ns('fn.method.name','fn.method.secondName');

and call using

fn.method.name

this function creates your namespace on 'window' so alternatively you can use

window.fn.method.name

1 Comment

the only problem with this is that you are explicitly making your new namespace an object literal and are unable to attach anything else (ie. functions) as you can see in the answer i chose above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.