3

I am used to the following syntax which is - I believe - widely used:

var foo = foo || {};

(function() { 
    foo.bar = function(){
         return this;
    };
    foo.bar.prototype.stuff = null;      
    foo.bar.prototype.do = function(){...};
})();

It could be done with or without closure.

I use the foo.bar.prototype.stuff syntax so as to not have all the definitions in the constructor itself.

With ECS6 I experimented with this syntax:

class Foo{};

class Bar{
    constructor(){
      this.stuff = null;
    }        
    get moreStuff(){ return this.stuff++;} 
    do(){...}
}

Foo.Bar = Bar;

module.exports = { Foo };

I find it very convenient that intellisense works in Visual Studio Code when using this syntax.

Can anyone see any issue with this syntax and if so amend it propose a better one?

I read this post How do I declare a namespace in JavaScript? and found many proposed syntax but most were given before ECS6.

pasx
  • 2,718
  • 1
  • 34
  • 26
  • Mostly I'd say, why assign `Bar` onto `Foo` at all? You can put both in `exports` and access them from there. – loganfsmyth Feb 03 '18 at 17:58
  • @loganfsmyth I have a C# background so I am used to structuring my code in hierarchical namespaces and I believe that's not uncommon in JavaScript either. If there is a better way, I'll use it. – pasx Feb 04 '18 at 21:34
  • Generally for modular JS, the file itself acts as the namespace, so you'd do `module.exports = Bar;` and that's that. If you need the class, you'd `require()` it using the filepath. – loganfsmyth Feb 04 '18 at 21:55

1 Answers1

2

In ES2015+, in the main you don't need these fake namespaces anymore. Instead, use modules. (Perhaps with a module loader, since native support for modules is still only just making its way into browsers.)

But if you want to continue using fake namespaces, perhaps temporarily until native support for modules becomes more widespread, what you have is fine, though there's no real advantage to Foo being declared with class than just making it an object as in your original example:

var Foo = Foo || {};
Foo.Bar = class Bar{
    constructor(){
      this.stuff = null;
    }        
    get moreStuff(){ return this.stuff++;} 
    do(){...}
};

But your version is fine other than giving the impression that Foo can be used to construct something useful, and other than the fact that if you do that in two files, it will fail (whereas your first example using var foo = foo || {}; is happy for you to do that in two files and include them both on the same page, perhaps one definign foo.Something and another defining foo.SomethingElse).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    This. There's nothing I could add. – Bergi Feb 03 '18 at 17:14
  • Thanks for the answer. Could you pls expand on how to structure namespaces with modules? – pasx Feb 03 '18 at 17:46
  • @pasx: You don't use these pseudo-namespaces with modules at all. You just `export` bindings from the module, and other code `import`s them. Nothing is global, and you don't have to use the same name when importing if you don't want to (you can export `Foo` and import `Bob`). This does away with naming conflicts (other than module identifiers). Any decent article on ES2015 modules should get you going. :-) – T.J. Crowder Feb 03 '18 at 17:53