7
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?

3
  • You may want to put var in front of Family and People, but, why not create a prototype for People, why do it for Family.People? Commented May 14, 2011 at 5:13
  • @James Black, that would give a syntax error in the second case... you can't have a var inside an object literal Commented May 14, 2011 at 5:14
  • The missing comma is at the end of line 3. Also, you definitely do not want to call Family = new function(...) {...}. new is used for object construction; in this case you just want Family = function(...) {...} Commented May 14, 2011 at 5:14

3 Answers 3

7

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()
Sign up to request clarification or add additional context in comments.

8 Comments

@Robert Awesome ;] thanks for the smashing code example. +1 for readability
With @Robert's refactoring, you can also elect to close over name and num if desired, to preserve encapsulation. Just refer to them directly and remove the assignment lines.
@Paul: Exactly! I updated my answer to include that information as well. Encapsulation makes them look as actual classes now...
@Robert: Cool, thanks for the hat tip. Technically, you don't even need to redeclare/assign the arguments in local scope, although that may be a point of style. I suppose it clearly shows we want to retain the argument.
@Deeptechtons: Check my edited answer that explains some more how to improve things even further.
|
5

Notice that you are assigning to Family.prototype.People then trying to access Family.People.

Family is not an instance of Family thus it does not have the properties of that class - Family is an instance of Function thus you are trying to access Function.prototype.People in that 3rd statement. (this is a bit of a simplification)

i.e. what you want to be doing is

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

You are also missing a comma before people, but I assume this is a typo...

2 Comments

Could you correct that code. I understood most of that explanation but couldn't derive at a solution. All i will be doing is var x = new Family('myName').Family.People.ClearNumber(); How do i do it properly.
see my edit (and why have you got that second Family there? you havn't set Family.prototype.Family so that would be undefined... what you want to call is var x = new Family('myName').People.ClearNumber();
0

You should declare the People constructor as a key in the Family object:

Family.People = function(num) {
  this._Number = num;
}

The Family prototype will be in the prototype chain for new objects of type Family; not a part of Family itself.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.