1

I have been studying as much as I can about the Module Pattern suggested by the Yahoo YUI Blog.

I've noticed that the YUI offers the ability to create a new empty namespace object without overwriting an existing one of the same name like so:

YAHOO.namespace("myProject");

Which can then be called and used with YAHOO.myProject

(Reminder: if YAHOO.myProject already exists it is not overwritten)

How can I achieve a similar effect using plain javascript, and without using the YUI?

Please explain with as much detail as possible.

The full YUI blog article where this is done can be found here.

As I am learning and srengthening my javascript knowledge and skills, I am trying to create my own personal javascript library (even if I never need to use it)

person0
  • 1,278
  • 2
  • 15
  • 20

3 Answers3

2

In your example, it could work like this:

if (!YAHOO.myProject) {
    YAHOO.myProject = {};
}
YAHOO.myProject.whatever = true;

or using your own parent module name:

var myModule = myModule || {};  // make sure parent is defined without overwriting
if (!myModule.myProject) {
    myModule.myProject = {};
}
myModule.myProject.whatever = true;

Or define your own namespace function:

function myNamespace(item) {
    if (!myModule[item]) {
        myModule[item] = {};
    }
}

myNamespace("myProject");
myNamespace.myProject.whatever = true;
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Okay, but if `myModule.myProject` already exists wouldn't the code you just wrote prevent the `myProject` object from being created? – person0 Feb 24 '12 at 05:46
  • @Proud_to_be_Noob - The point of namespace initialization is to initialize it if it doesn't already exist and leave it alone if it does exist. That's what this code does. Are you trying to do something else? – jfriend00 Feb 24 '12 at 06:10
  • I'm trying to understand what the YUI people make happen when they use their namespace function, because their wording implies that they can create an empty duplicate object without overwriting it. I'm also just trying to figure out a nice way to do basically what is being shown. (I like the defining of my own namespace function you just posted, that helps me understand a lot - thanks!). – person0 Feb 24 '12 at 06:22
  • @Proud_to_be_Noob - No. Yahoo doesn't create an empty duplicate object. They just do what I described above. They initialize it if it doesn't exist and leave it alone if it does exist. You can't have two objects with the same name nor would you want to. – jfriend00 Feb 24 '12 at 06:26
  • Right that's what I figured, so if it already exists, it just allows you to use the already existing one and add properties and methods on to it but not allowing you to change the original `myProject` object then right? – person0 Feb 24 '12 at 06:35
  • @Proud_to_be_Noob - you're trying to make this far too complicated. If you want to assign a new property to a namespace object, you have to make sure the root exists before you can add a property to it. That's ALL this code does. – jfriend00 Feb 24 '12 at 06:37
1

Q. How can I create an empty namespace object without overwriting another object with the same name?

You can't. By definition the same name can't refer to both your new empty object and an existing object.

If you mean "How can I check create an empty namespace object only if it doesn't already exist, otherwise I want to add to the existing one", then you just do this:

if (!YAHOO.myProject)
   YAHOO.myProject = {};

// or you may see this variation:
YAHOO.myProject = YAHOO.myProject || {};

I don't like the latter but it is used frequently to achieve the same effect as a plain if statement.

To take this general principle much further have a look at this article: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

UPDATE: According to the YUI API documentation for YAHOO.namespace(), the method "Returns the namespace specified and creates it if it doesn't exist" - which you'll note is much less ambiguous than the wording of the blog you were reading, and pretty much backs up what I already said...

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • I understand everything that you just said, and it is exactly what I was thinking before, so then why does the YAHOO YUI blog claim, "This assigns an empty object myProject as a member of YAHOO (but doesn’t overwrite myProject if it already exists). Now we can begin adding members to YAHOO.myProject." Does the YUI somehow auto-reassign the duplicate `myProject` an alternate name? – person0 Feb 24 '12 at 05:53
1

Edit Just realized I'm not directly answering your question. Sorry! However hopefully this will help you understand some alternate techniques.

This is a technique I use from time to time, such as when I want to add a property or function once and not allow it to be overwritten later.

    var module = new function(){

        var modules = {}; //internal module cache

        return function(name, module){
            //return all modules
            if( !name ) return modules;

            //return specific module
            if( modules[name] ) return modules[name];

            //return the module and store it
            return modules[name] = module;
        }

    }

So you can use it like so:

//will store this since it doesn't exist
module('test', 'foo'); //Since 'test' doesn't exist on the internal 'modules' variable, it sets this property with the value of 'foo'

module('test'); // Since we aren't passing a 2nd parameter, it returns the value of 'test' on the internal 'modules' variable

module('test', 'bar'); //We are attempting to change the value of 'test' to 'bar', but since 'test' already equals 'foo', it returns 'foo' instead.

module(); // { 'test': 'foo' } //Here we aren't passing any parameters, so it just returns the entire internal 'modules' variable. 

The key thing to look at is that we're using 'new function()'. This is done at assignment, because we really want 'module' to be the internal function, not the outer. But in order to create a closure for the internal 'var modules' variable, the outer function has to execute on assignment.

Also notice that you could write the outer function to be self executing too:

var module = function(){
    var modules = {};
    //other stuff
}();
Geuis
  • 41,122
  • 56
  • 157
  • 219
  • Could you put a few more comments in the second section where you show how to use it. I understand the first part, I just want to make sure I understand the second part. What happens in the code -in the second section- if you add `module('test2', 'foo2');` in addition to what you have? – person0 Feb 24 '12 at 06:03
  • Then it will add a new property onto the internal modules object called 'test2': 'foo2'. Basically it lets you set properties once without being able to change them later. – Geuis Feb 24 '12 at 06:12
  • Okay, I think I understand that but what I meant was could you explain more about how the code reacts to each of these `module('test', 'foo'); module('test'); //'foo' module('test', 'bar'); //foo module(); // { 'test': 'foo' }` and what they each do? – person0 Feb 24 '12 at 06:13
  • If you want to get the kind of behavior where you protect properties from being changeable after being set but on a native object, like obj.prop = 1; obj.prop = 2; //stays 1, then you have to use ES5 getter/setters which aren't supported in all browsers. Otherwise you have to simulate it with an accessor function. – Geuis Feb 24 '12 at 06:15
  • Added some more explanations of what's happening. Does that help? – Geuis Feb 24 '12 at 06:18
  • Oh yeah, that helps a ton! Thanks! So then if you did `module('test2', 'foo2');` would it just set `test2` as another property with the value of `foo2`? and could you do that for any number of properties? If so then calling `module()` would return all of the modules variable icluding parameters etc? So could you then use it as for example `document.write(module.test);` and `document.write(module.test2);` which would print out "foo" and "foo2" respectively? And then you could never overwrite those values? – person0 Feb 24 '12 at 06:30
  • If you have gmail, would be happy to chat on gchat. Would be quicker than commenting back and forth =) geuis.teses@gmail.com – Geuis Feb 24 '12 at 06:31