Search code examples
javascriptclassobjectconstructorobject-literal

UnCaught TypeError - Nested objects in Javascript? Why is this not allowed? Object literal notation works


Playing around with some JS tests and I'm trying to instantiate some nested objects in my v namespace. As you'll see below, ClassA and ClassB work as expected. When I try and nest some objects under another property (myCustomProperty) I start running into issues! Could someone explain?

Below is the original code:

var v = (v) ? v : {};

v.someClassA = (function() {
   this.hello = function() {
        console.log("Class A Hello!");
    }
});

v.someClassB = (function() {
   this.hello = function() {
        console.log("Class B Hello!");
    }
});

// this all works! 
var myClassA = new v.someClassA();
var myClassB = new v.someClassB();


v.myCustomProperty = (function() {

    function someClassC() {
        this.hello = function() {
            console.log('C');
        }
    }

    function someClassD() {
        this.hello = function() {
            console.log('D');
        }
    }

    return {
        someClassC: someClassC,
        someClassD: someClassD
    }
});

// Uncaught TypeError: v.myCustomProperty.someClassC is not a function! Why?
var myClassC = new v.myCustomProperty.someClassC();
var myClassD = new v.myCustomProperty.someClassD();

myClassA.hello();
myClassB.hello();
myClassC.hello();
myClassD.hello();

If I change my declaration of v.myCustomProperty to use object literal notation, then it ALL WORKS! :

v.myCustomProperty = {
    someClassC: function() {
        this.hello = function() {
            console.log('C');
        }
    },
    someClassD: function() {
        this.hello = function() {
            console.log('D');
        }
    }
 }

I guess my question really is how would I make this work using the notation in my original snippet? Possible? Horrible practice to do it that way?

Thanks!


Solution

  • v.myCustomProperty is a function that returns an object. You have to call the function first:

    new (v.myCustomProperty().someClassC)();
    //                     ^^
    

    Otherwise, v.myCustomProperty.someClassC() tries to access the property someClassC of the function, and we all know (hopefully) that functions don't have such a property.


    Or maybe you intended to execute the function immediately and assign the object to myCustomProperty?

    v.myCustomProperty = (function() {
      // ...
    }()); // <- call function