1

What I am interested to know is if there is a shorter way of achieving the following:

App.Plugins = App.Plugins || {};
App.Plugins.SomePlugin = App.Plugins.SomePlugin || {};
App.Plugins.SomePlugin.Models = App.Plugins.SomePlugin.Models || {};
App.Plugins.SomePlugin.Views = App.Plugins.SomePlugin.Views || {};
App.Plugins.SomePlugin.Collections = App.Plugins.SomePlugin.Collections || {};

As far as I know, this format is fine, please someone let me know if I'm mistaken, I'm just wondering if there is some nicer way of doing this initial setup on my singleton.

Thanks in advance...

Matt
  • 4,107
  • 3
  • 29
  • 38
  • 1
    You could write a method to smash these out for you: `buildTree(App, 'Plugins', 'SomePlugin', 'Models')` etc that could work like `mkdir -p` – tadman Jan 27 '14 at 14:54
  • Absolutely, however given the infrequency with which this is performed and in the interest of keeping code simple it makes less sense than above. I was wondering if there was some one-liner but I think not – Matt Jan 27 '14 at 15:06

3 Answers3

3

You could do the following:

function defaults(obj, prop) {
    return obj[prop] = obj[prop] || {};
}
defaults(App, 'Plugins');
defaults(App.Plugins, 'SomePlugin');
defaults(App.Plugins.SomePlugin, 'Models');
defaults(App.Plugins.SomePlugin, 'Views');
defaults(App.Plugins.SomePlugin, 'Collections');
Joeytje50
  • 18,636
  • 15
  • 63
  • 95
  • I considered creating a function to do so, in truth though this is as many lines of code as the manual approach provided in the question, it also adds another potential point of failure, I believe the answer to my question is probably no. Thanks for the response though. – Matt Jan 27 '14 at 15:05
  • If you're worried about a "point of failure" you don't have a very good test suite. Maybe you need to address that first. – tadman Jan 27 '14 at 15:07
  • You should reword that to "don't have a test suite", I have just joined this project and it is #1 on my priority list! Truth is, I don't think this adds any value over the initial approach, I accept it as a perfectly valid answer though, thanks for your insight both – Matt Jan 27 '14 at 15:33
1

I don't understand exactly why you do this

Anyway a shorter way to write that is:

App={
 Plugins:{
  SomePlugin:{
   Models:{},
   Views:{},
   Collections:{}
  }
 }
}

then considering the function

function defaults(obj, prop) {
    return obj[prop] = obj[prop] || {};
}

would return an error using

defaults(App.Plugins.AnotherPlugin,'Models')

checking this is a pain:

var x={};
if(App&&
   App.Plugins&&
   App.Plugins.AnotherPlugin&&
   App.Plugins.AnotherPlugin.Models
){
 x=App.Plugins.AnotherPlugin.Models
}
console.log(x);

A solution is

var x={};
try{x=App.Plugins.AnotherPlugin.Models}catch(e){}
console.log(x)

this gives you no errors

but you can't set it the easy way.

EDIT

comment answer

Then you should start checking at the point where nothing is certain. In your case you just need to check if anotherPlugin exists.you probably already have App & App.Plugins.so you don't need App=App||{}, but only App.Plugins.AnotherPlugin

!App.Plugins.AnotherPlugin||App.Plugins.AnotherPlugin=NewPlugin

or a function

function addPlugin(name,newPlugin){
 !App.Plugins[name]||App.Plugins[name]=newPlugin
}

An define your own standards... I mean why return an object if it does not exist?

if it does not exist you can't do anything anyway.

and again the biggest problem is always to check if it exists... and like i already described above it is try catch.

EDIT2

check this function.

function def(a,b,c,d){
 c=b.split('.');
 d=c.shift();
 a[d]||(a[d]={});
 !(c.length>0)||def(a[d],c.join('.'));
}

usage:

var A={};
def(A,'B.C.D.E.F')
//this transforms your {}
//to 
A:{
 B:{
  C:{
   D:{
    E:{
     F:{
     }
    }
   }
  }
 }
}

http://jsfiddle.net/5NgWL/

to create your plugin:

var App={}
def(App,'Plugins.SomePlugin.Models')
def(App.Plugins.SomePlugin,'View')
// &/or
def(App,'Plugins.SomePlugin.Collections')
cocco
  • 16,442
  • 7
  • 62
  • 77
  • My reason for doing this is that the App object already exists at the point of executing my code, I am supplementing it with additional containers for my application components. I am definitely interested in any criticism you have of this – Matt Jan 27 '14 at 15:37
  • toke me a while to create a custom function but it's here now ... check it out. – cocco Jan 27 '14 at 16:21
  • Agreed with comment answer, at this stage this is the only place in the code this approach is taken, App is already validated but the rest aren't. Going forward I would have the App.Plugins check somewhere higher up the chain as individual plugins need not concern themselves. – Matt Jan 27 '14 at 16:24
  • Also +1 for the elegant function. Accepted as the most robust and insightful answer. – Matt Jan 27 '14 at 16:26
0

May be use it

function namespace(path) {
    var segments = path.split('.'),
        result = {};

    function define(name, obj) {

        if (name === '.') {
            return obj;
        } 

        !obj[name] && (obj[name] = {});
        return define(segments.shift(), obj[name]);
    }

    segments.push('.'); //add stop symbol;
    define(segments.shift(), result);

    return result;
}

namespace('App.Plugins.SomePlugin.Collections').controller = function() {}
Burlak Ilia
  • 185
  • 4