views:

84

answers:

3

My problem is with objInfo(). How can I return an object via a passed-in variable? I'm trying to namespace my code and use private/public vars.

Bonus Q: How would you otherwise improve the code?

// Namespace all my code
var bab = new function() {

    // Declare cat object
    function cat()
    {
      this.eyes = 2;
      this.legs = 4;
      this.diet = 'carnivore';

      return true;
    }

    // Declare lion object
    function lion()
    {
      this.mane = true;
      this.origin = 'Africa';
      this.diet = 'people'; // has priority over cat's diet

      return true;
    }

    // Make lion a subclass of cat
    lion.prototype = new cat();

    // Create an instance of class lion
    var simba = new lion();

    // Share diet publicly
    this.objInfo = function(name) {
        return name; // simba works, name doesn't
    };

};

alert(bab.objInfo('simba').diet);

Note: Source is sampled from various places

+4  A: 
T.J. Crowder
Excellent code review!
Blair McMillan
I can't thank you enough. But I'll try, Thanks*(1/0). Nope, didn't work.
Matrym
@Matrym: LOL!! No worries, glad that helped.
T.J. Crowder
A: 

You could use eval, but I would hate to recommend that.

You might improve the script by "registering" your lions in an array.

// Namespace all my code
var bab = (function() {
        // Declare cat object
        function cat() {
            this.eyes = 2;
            this.legs = 4;
            this.diet = 'carnivore';

            return true;
        }

        // Declare lion object
        function lion() {
            this.mane = true;
            this.origin = 'Africa';
            this.diet = 'people'; // has priority over cat's diet

            return true;
        }

        // Make lion a subclass of cat
        lion.prototype = new cat();

        // Create an instance of class lion
//      var simba = new lion();
        var lions = {}; // Create a "lions" object to collect all of the lion instances
        lions["simba"] = new lion();

    return {
        // Share diet publicly
        objInfo: function(name) {
            return lions[name];
        };
    }
})();

alert(bab.objInfo('simba').diet);

I've edited the code to use a less error-prone form of encapsulation. This article helped me a lot: Public and Private in JavaScript.

palswim
Or go to the more definitive work by Crockford: http://javascript.crockford.com/private.html
T.J. Crowder
@T.J. Crowder: Yeah, that one, too, but that one is a bit more abstract. The Dustin Diaz article introduced me to the concept to the point where I understood it, then the Crockford article completed my understanding.
palswim
@palswim: Yeah, Crockford makes for dense reading. Would have been nice if Dustin Diaz had cited his sources, though, since he almost certainly read Crockford or someone who had read Crockford. :-)
T.J. Crowder
+1  A: 

You have essentially made all but objInfo() in bab obsolete, since objInfo() simply returns exactly what is passed into it.

In your specific case, objInfo("simba") doesn't work since objInfo() simply returns the string "simba":

    ...
    // Share diet publicly
    this.objInfo = function(name) { // <-- If name == "simba"
        return name; // <-- This will return "simba" not the Object simba!!!
    };

};

alert(bab.objInfo('simba').diet);​ // This will check for the diet property of
                                  //   the string "simba". So it won't work.

However there is a larger problem, as I mentioned before. objInfo() simply returns exactly what is passed into it!

Try out these examples:

alert(bab.objInfo('simba'));            // This will alert "simba"
alert(bab.objInfo('noodles'));          // This will alert "noodles"
alert(bab.objInfo(window).innerWidth);  // This will give you the innerWidth of

jsFiddle example of alert(bab.objInfo(window).innerWidth);


You have essentially "short circuited" your entire bab object. Only the objInfo method "does" anything.


This is how I would do it:

// Namespace all my code
var bab = new function() {    
    var cat = function() // Declare cat object
    {
      var protected = {}; // Protected vars & methods
      protected.eyes = 2;
      protected.legs = 4;
      protected.diet = 'carnivore';
      return protected; // Pass protected to descendants
    }
    var lion = function()
    {     
      var protected = cat();  // Make lion a subclass of cat        
      var public = {}; // Public vars & methods
      public.legs = protected.legs; // Make 1 protected var public
      public.mane = true;
      public.origin = 'Africa';
      public.diet = 'people'; // has priority over cat's diet
      return public; // Make public vars available
    }    
    var simba = lion();     // Create an instance of class lion
    simba.diet = "Asparagus"; // Change simba, but not lion
    // Get property of choice
    this.objInfo = function(property) {
        return ("Simba: " + simba[property] +
                " - Lion (this is usually private. Shown for testing.): " +
                lion()[property]);
    };
};
alert(bab.objInfo("diet"));

jsFiddle example


I used functional inheritance in the above. I find it simpler to work with and it makes good use of the classless nature of Javascript's Object Oriented persona.

As test output, I returned directly from lion... which you would not usually do, just to show that changing Simba doesn't change lion. You can tell that the lion's diet has priority over the cat's diet, just like you wanted.

The trick is to package your protected and public variables and methods in returned objects, and don't forget that you can also create methods in you felines.

Peter Ajtai