9

I have read that creating a namespace for JavaScript projects helps to reduce conflicts with other libraries. I have some code with a lot of different types of objects for which I have defined constructor functions. Is it good practice to put these inside the namespace as well?

For example:

var shapes = {
    Rectangle: function(w, h) {
        this.width = w;
        this.height = h;
    }
};

which can be called via:

var square = new shapes.Rectangle(10,10);
Filburt
  • 17,626
  • 12
  • 64
  • 115
Joe
  • 4,852
  • 10
  • 63
  • 82
  • Your constructor, which is a function, becomes a *function expression* instead of a *function declaration* if you assign it to an object property in a "namespace" instead of simply writing `function Rectangle(w, h) {}`. This has has slight differences: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions Other than that, it doesn't pollute the global namespace, which is a good thing, as others have pointed out. – caw Nov 13 '17 at 02:38

5 Answers5

5

This is generally a good idea; additionally, if your objects require a set of shared functions that should not be exposed you can wrap them all inside a closure, like a module:

var shapes = (function() {
  // private variables
  var foo = 0;

  // private function
  function get_area(w, h)
  {
    return w * h;
  }

  return {
    Rectangle: function(w, h) {
      this.width = w;
      this.height = h;
      // call private function to determine area (contrived example)
      this.area = get_area(w, h);
    }
  }
}());

var s = new shapes.Rectangle(100, 5);
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
4

This namespacing is called the "Singleton pattern" and it's one of the main patterns reccomended by the famous "Gang of Four" design patterns book.

From the great (and free) book Learning JavaScript Design Patterns:

Classically, the Singleton pattern can be implemented by creating a class with a method that creates a new instance of the class if one doesn't exist. In the event of an instance already existing, it simply returns a reference to that object.The Singleton pattern is thus known because it restricts instantiation of a class to a single object.

In JavaScript, singletons serve as a namespace provider which isolate implementation code from the global namespace so as to provide a single point of access for functions.

They can take on a number of different forms, but in its most basic, a Singleton could be implemented as an object literal grouped together with its related functions and properties...

So yes, it's a well used concept in many programming languages and a great for preventing global namespace object collisions in JavaScript.

See also: Simplest/Cleanest way to implement singleton in JavaScript?

Community
  • 1
  • 1
buley
  • 28,032
  • 17
  • 85
  • 106
  • 1
    Great. Thanks a lot. Also thanks for the links. I just hadn't seen any examples of anyone calling `new` for a function in a namespace and wondered if there was a reason for that. – Joe Jun 10 '12 at 16:42
  • No reason that I can think of. The new function is JavaScript's prototypical inheritance, which is often used in practice as more of a class-like inheritance. Most examples you'll see define just a single "class," but if you're trying to organize a bunch of them the singleton pattern is equally if not more useful. – buley Jun 10 '12 at 16:55
  • 2
    @joe of course, it's not considered singleton pattern if the object literal contains constructors ;-) – Ja͢ck Jun 10 '12 at 17:40
2

Yes. You should pollute the global namespace the least possible

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
2

Yeah, that's a good idea, because you avoid the hassle and confusing caused by polluting the global namespace. Although I personally would change shapes to shape, so you could then have a shape.Rectangle, which makes a little more sense to me (after all, a Rectangle is only one object).

Elliot Bonneville
  • 51,872
  • 23
  • 96
  • 123
1

Besides not polluting the namespace, it also enables you to do type family checking:

function doSomethingTo(shape) {
  var shapeName, validArg;

  for (shapeName in shapes) {
    validArg = validArg || shape instanceof shapes[shapeName];
  }

  if ( !validArg ) throw "Argument is not a shape.";
}
Tomalak
  • 332,285
  • 67
  • 532
  • 628