views:

227

answers:

5

It is fairly well known in JavaScript that declaring variables within the global scope is a bad thing. So code I tend to work on contains namespaced JavaScript.

There seems to be two different approaches taken to this -

  1. Adding your application specific functions to the libraries' namespace e.g. $.myCarouselfunction
  2. Creating your own namespace e.g. MyApplication.myCarouselFunction

I wanted to know whether or not there is a better solution or if they tend to meet somewhere close in terms of pros and cons.

The reason for me personally deciding not to go with the library so far is for Seperation / Isolation / Lack of conflict with library code and potential plugins that are likely to share that namespace. Is there more to this that I'm not considering?

+1  A: 

I tend to prefer adding custom code to the library myself. The biggest reason for that is so that the usage semantics remain consistent across the built-in code and my custom code. That being said I can't really think of any technical advantages or disadvantages to this approach. I think your concern about conflicts is valid, though probably not very likely (if you end up with a component/module that conflicts with one of your custom functions, chances are it will be because you are replacing your code with someone else's).

ckramer
+1  A: 

The correct choice depends on your target environment. You're choosing between two namespaces, both of which can become arbitrarily cluttered. If you think it's more likely that you'll encounter a conflict in the library namespace, you should use the window namespace. If you think the window namespace is more likely to get cluttered, choose the library namespace.

In either case, you usually should only create one "global" name. In other words, if you're going to put your function in the library's namespace, it's best not to name it $.myFn. Name it $.yaya3.myFn and then cache a local reference to it in any context where you're calling myFn multiple times.

One best practice for referencing your function is to pass the namespace that it lives in as an argument to an anonymous function:

(function (yaya3) {   
var myFn = yaya3.myFn;
myFn("frobnard!");
}(window.yaya3)); // you could instead pass $.yaya3 or YUI.namespace("yaya3") here

This makes it much easier if you discover that you need to move to a different namespace.

lawnsea
I don't really see what this buys you. First, as a library maintainer, I wouldn't make a yaya4 unless it wasn't going to be backwards compatible, in which case you have to audit your code anyway; and secondly, if you did want to change to yaya4, wouldn't wouldn't the code be more readable if you just replaced all references to yaya3 with yaya4?
Alex M.
+12  A: 

I think the most important thing in choosing this sort of thing is semantics.

Does your function/class extend or depend on a library-specific feature? Put it in the library namespace.

Is your function/class library-independent? In this case, it is better to put it in a custom namespace. This makes it possible to reuse your code outside the the library you originally used it with.

Jani Hartikainen
I agree, but bear in mind that by using namespaces you avoid potential names clashes, especially after a library update and particularly en javascript where you can redefine a variable and everything continues like nothing's happened.
+1 this answer is the definite winner for me.
Sohnee
+2  A: 

If you've ever tried to pull in more than one library using the same namespace, it can be surprising how likely collisions are to occur, and it can be quite frustrating in that these sorts of bugs often crop up in surprising and hard to debug ways. I think that your intuition about collisions is correct, and that the most import consideration as to whether to define your own namespace or reuse someone else's is to respect namespace ownership. That means that that unless you are in contact with the people who maintain another namespace and they know what you are doing, it's a good idea to use your own namespace.

If you do decide to ignore the advice on namespace ownership and define an API on an existing namespace (for semantics or whatever), one thing to consider would be to use an export function to detect errors. Basically, you can first define something on your own namespace, and then export it to the target namespace, along the lines of:

MyApplication.exportName = function(objToExportTo, name, obj) {
  if (objToExportTo[name] === undefined) {
    objToExportTo[name] = obj;
  } else {
    // Possibly assert!
  }
};

MyApplication.myCarouselFunction = function() { ... };
MyApplication.exportName($, 'myCarouselFunction', MyApplication.myCarouselFunction);
Alex M.
+3  A: 

Personally I like this sort of approach:

(function(namespace) {

function myPrivateFunction(){};

namespace.myPublicFunction = function(){};

})($); // passing the $ namespace, but if it clutters, 
       // we can change it to something else
Luca Matteis