1

I was wondering what the community of javascript developers say about when to nest vs when to split code

Essentially lets say you are running some code within an IIFE

Why is it that a lot of times I see things like

(function(context) {
    context.bang = {
        someTing: function() {
           //a lot of code
        },
        someTingElse: function() {
           //a lot of code
        }
    }
}(this));

vs

(function(context) {
    function doSomething() {
        // a lot of code
    }
    function doSomethingElse() {
        // a lot of code
    }
    context.bang = {
      someTing : doSomething,
      someTingElse : doSomethingElse
    }
}(this));

I find the second piece of code much more readable, and if you want it compressed send it through something like google's closure compiler which will take the second version of the code and condense it down to essentially the first + tricks you didn't think of. Code is to be maintained by people, optimized by compilers, and run by applications.

Edit:

though not apparent in this example lets just keep with the trend of putting children functions within children functions, Also I don't care about whats more scoped then something else within my iife as long as nothing creeps back out into context

but along the same trend the end result of most actual final code I see is like

(function(context) {
    context.bang = {
        someTing: function() {
           return {
               another: function() {
                  return {
                     yetAnotherFunction: function() {
                        return true;
                     }
                  }
               }
           };     
        }
    }
}(this));

where each function level deep is more then just the one or two line functions im making here rather then

(function(context) {
    function yetAnotherFunction() {
       return true;
    }
    function another() {

       return yetAnotherFunction;
    }
    function someTing() {
       /*blahblahblah*/
       return another;
    }
    context.bang = {
        someTing: someTing
    }
}(this));  
diceu
  • 13
  • 5
  • How is this Javascript-specific? It's like programming in any other language -- you should try to keep your functions to a manageable size, and give them meaningful names for abstraction purposes. This is just good program design, as has been taught to generations of programmers. – Barmar Aug 16 '13 at 00:39
  • It actually is javascript specific because as seen from @Johnathan's response, declairations and expressions are treated differently. Also I have no formal education in programming. – diceu Aug 16 '13 at 01:06

2 Answers2

1

In many cases, they're equivalent and it's just a matter of personal preference.

Semantically, the 1st uses function expressions while the 2nd uses function declarations, so the 2nd gets hoisting.

But, the main difference is in what options each function has to access another. Having them separate of the Object utilizes the IIFE as a closure to allows them to reach another as locals:

(function(context) {
    function doSomething() {
        // ...
    }
    function doSomethingElse() {
        doSomething();
    }
    // ...
}(this));

But, they can always assume this will be a fitting object as well:

(function(context) {
    context.bang = {
        someTing: function() {
            // ...
        },
        someTingElse: function() {
            this.someTing();
        }
    }
}(this));

this may not always be the Object that was defined, but somethings that's desired.

Side note: the parenthesis around the function expressions aren't necessary when an Expression is already expected, like after a : in an Object literal.


Regarding your edit:

Well, it's no longer simply about style and which is readable. It's now about intended logic and which is necessary.

With the 2nd (or 4th) snippet, each function returns a reference to another already-existing function.

this.someTing() === this.someTing(); // true

With the 1st (or 3rd), however, every call to any of them creates a new function from the same definition.

this.someTing() === this.someTing(); // false

Sometimes the creation of a new function from a particular definition is necessary (again: Closures). Other times, it can just be a waste of resources.

Community
  • 1
  • 1
Jonathan Lonowski
  • 112,514
  • 31
  • 189
  • 193
  • Thanks, I have learned a lot of new words from your explanation, I believe you originally meant that example 2 gets hoisting (the declairations). – diceu Aug 16 '13 at 01:02
  • @diceu Yeah. Sorry. I was focusing on the snippets out of order. Apparently, a bit of that sneaked into my answer. :) – Jonathan Lonowski Aug 16 '13 at 01:32
0

I find the first equally readable and more concise. Why should I type the same function name twice? I would also omit the parentheses around the anonymous functions in the object. Just user more line breaks if you are running out of space. One shouldn't cram too much into one line anyway. Also my editor had guidelines. You could also do this btw:

function(context){
    context.obj = {};
    obj.a = function(){
        // Your code
    }
    obj.b = function(){
        // Your code
    }
}(this)

this

Important to note is that this will refer to different objects within the function in the examples you gave.

In the first it will refer to the outer function. In the latter it will refer to context.bang

However I don't see why the original code isn't just

this.obj = {};
this.obj.a = function(){
    // Your code
}
this.obj.b = function(){
    // Your code
}
kaan_a
  • 1,789
  • 14
  • 30
  • well its readable now, but exchange `// a lot of code` with a lot of code and you lose your readability when you are 3 levels indented (like in the first example) vs 2 (like in the second). Essentially its a matter of preference I suppose but I would rather see a bunch of code indented 2-3 levels deep max and split up then 1 chunck of code indented 8 levels deep. – diceu Aug 16 '13 at 00:13
  • As for your edit, I like wrapping everything in IIFE so as to garuntee no scope creep as well as setting up for later possible private variables. Normally What I will do is function declarations and then attach my initialize function to some event listener like window.onload(); – diceu Aug 16 '13 at 01:18