Search code examples
javascriptoopclassobjectprototype-programming

Javascript prototype and issues accessing class


Family = function(name) {
  this._Name = name;
}

Family.prototype = {
  getName: function() {
    return this._Name;
  },
  People: function(num) {
    this._Number = num;
  }
}

Family.People.prototype = {
  clearNumber: function() {
    this._Number = 0;
  }
}

People is a nested class. Its parent class is Family.

I get the error that Family.People is undefined. Could someone correct the code above?


Solution

  • Working code

    // function doesn't need "new" operator
    var Family = function(name) { this._Name = name; };
    
    Family.prototype = {
        getName: function() { return this._Name; }, // missing comma
        People: function(num) {
            this._Number = num;
        }
    };
    
    // work with prototypes
    Family.prototype.People.prototype = {
        clearNumber: function() { this._Number = 0; }
    };
    

    This will work. But you have to be aware, that when you call:

    var f = new Family("Doe");
    

    f.People is just an object constructor, and not an instance of some other object. You will have to instantiate it as well like:

    f.members = new f.People(3);
    

    Sou you have a constructor within your instance which is rather confusing.

    A better approach

    So it would probably be better if you'd write your prototypes this way:

    var Family = function(name) {
        this._Name = name;
        this.getName = function() { return this._Name; };
    };
    
    Family.People = function(num) {
        this._Number = num;
        this.clearNumber = function() { this._Number = 0; };
    };
    

    This actually makes a class within a class (and not within instances). So upper lines would be called this way:

    var f = new Family("Doe");
    f.members = new Family.People(3);
    

    Drill down of f instance would look like:

    f
      _Name
      getName()
      members
        _Number
        clearNumber()
    

    Private variables

    var Family = function(name) {
        var _name = name;
        this.getName = function() { return _name; };
    };
    
    Family.People = function(num) {
        var _num = num;
        this.getNumber = function() { return _num; }
        this.clearNumber = function() { _num = 0; };
    };
    

    This way we make variables private and only accessible within so they can't be manipulated outside. You must always use functions to manipulate them. This makes it more robust especially when there are certain business rules related to variable values.

    var f = new Family("Doe");
    f._name; // this is undefined because "_name" is private closure variable
    

    Drill down of f instance would now look more like a class object instance:

    f
      getName()
      members
        getNumber()
        clearNumber()