PDA

View Full Version : unclear example from Flanagan's createNamespace function



Jason57
Jan 7th, 2010, 06:47 PM
The code from his example 10-5 below, I understand mostly what he is trying to do here however I do not quite understand why he constructed the for loop as he did in bold. After the first iteration, he sets container = container[part]; so container is set to either an empty object or a valid global object (if it exists).

If set to the former, ie. an empty object, do subsequent iterations of the loop delete that specific object (part) that was created from the parsed input string "name"? If so do we care? Could this have been written more eloquently or am I not fully understanding his intentions?
Thanks J.





/**
* This function creates and returns a namespace object for the
* specified name and does useful error checking to ensure that the
* name does not conflict with any previously loaded module. It
* throws an error if the namespace already exists or if any of the
* property components of the namespace exist and are not objects.
*
* Sets a NAME property of the new namespace to its name.
* If the version argument is specified, set the VERSION property
* of the namespace.
*
* A mapping for the new namespace is added to the Module.modules object
*/
Module.createNamespace = function(name, version) {
// Check name for validity. It must exist, and must not begin or
// end with a period or contain two periods in a row.
if (!name) throw new Error("Module.createNamespace(): name required");
if (name.charAt(0) == '.' ||
name.charAt(name.length-1) == '.' ||
name.indexOf("..") != -1)
throw new Error("Module.createNamespace(): illegal name: " + name);

// Break the name at periods and create the object hierarchy we need
var parts = name.split('.');

// For each namespace component, either create an object or ensure that
// an object by that name already exists.
var container = Module.globalNamespace;
for(var i = 0; i < parts.length; i++) {
var part = parts[i];
// If there is no property of container with this name, create
// an empty object.
if (!container[part]) container[part] = {};
else if (typeof container[part] != "object") {
// If there is already a property, make sure it is an object
var n = parts.slice(0,i).join('.');
throw new Error(n + " already exists and is not an object");
}
container = container[part];
}

// The last container traversed above is the namespace we need.
var namespace = container;

// It is an error to define a namespace twice. It is okay if our
// namespace object already exists, but it must not already have a
// NAME property defined.
if (namespace.NAME) throw new Error("Module "+name+" is already defined");

// Initialize name and version fields of the namespace
namespace.NAME = name;
if (version) namespace.VERSION = version;

// Register this namespace in the map of all modules
Module.modules[name] = namespace;

// Return the namespace object to the caller
return namespace;
}

rnd me
Jan 7th, 2010, 09:38 PM
he's turning a path into a tree.
since you can only set a property on an exsiting object, you can only move to the right one dot at a time.

for example, consider "ob={};".
i can set "ob.prop=1" just fine, but i can't set "ob.prop2.prop3", since at the time i try, there is no ob.prop2 property.

what your code does is gradually add named object property objects.
the loop tacks them on gradually.

the trace for "prop.path1.path2" might be something like:



namespace={};
namespace["prop"]={};
namespace["prop"]["path1"]={};
namespace["prop"]["path1"]["path2"]={};

but if i just tried to set
namespace["prop"]["path1"]["path2"]={};first, it would not work.


does that make sense?

Jason57
Jan 8th, 2010, 12:58 AM
Thanks rnd me

I'm still in JavaScript diapers, still learning the core language. I guess what confuses me is if the path name is "prop.path1.path2". And where the code is: if (!container[part]) container[part] = {}; //creates an empty object, then does this: container = container[part]; So if container contains the empty object of prop first, then contains the empty object of path1 then path2.

So my question is, when the for loop finishes is there existing objects for prop and path1? Assuming prop and path1 never existed before the call to the function. If so how to check (might be a mute question).
J.

rnd me
Jan 8th, 2010, 01:07 AM
So my question is, when the for loop finishes is there existing objects for prop and path1? Assuming prop and path1 never existed before the call to the function. If so how to check (might be a mute question).
J.

i think so, all are parts are objects, but they are nested.

this is the source view of your namespace object after the code finishes:

namespace={
prop:{
path1:{
path2:{}
}
}
};

Jason57
Jan 8th, 2010, 01:24 AM
i think so, all are parts are objects, but they are nested.

this is the source view of your namespace object after the code finishes:

namespace={
prop:{
path1:{
path2:{}
}
}
};

So then the following code should work?


if (namespace.prop)
alert("prop is property in namespace");


and this should work?


if ("prop" in namespace)
alert("prop is property in namespace");

rnd me
Jan 8th, 2010, 03:05 AM
So then the following code should work?


if (namespace.prop)
alert("prop is property in namespace");


and this should work?


if ("prop" in namespace)
alert("prop is property in namespace");


yes and yes.

Jason57
Jan 8th, 2010, 05:27 PM
yes and yes.

I agree, but the code is not doing that, I tested it. In essence, this is what the for loop is doing;

var container=this;
var name="str1.str2.str3";

//begin for loop
container["str1"]={};
container=container["str1"]; // result of loop 1

container["str2"]={};
container=container["str2"]; // result of loop 2

container["str3"]={};
container=container["str3"]; // final loop
//end for loop

var namespace=container; // str1 and str2 is irrelevant at this point weather they existed or not

So upon completion of the last loop, namespace is just an empty object with no properties. So what would have been more clear is if the author parsed the last delimited string "str3" and created the empty object and assigned it to namespace directly, thus eliminating the need for a for loop.

Please correct me if I'm wrong.

Jason57
Jan 8th, 2010, 09:21 PM
Please ignore my last post. This issue finally sunk in. You were correct rnd me, I did not see that it was building a nested object tree.
Most humble apoligies,
J.