JavaScript statics, enums, and functional inheritance

In this article I am going to show you how you can use enums and static properties in JavaScript.

I am going to use a small example where Person inherits from Contact, and there is an enum that defines the two possible genders; Male, and Female.

The result of running the example looks like this:

We create a contact specifying name, gender, and phoneNumber, and then we write the result from the toString method to the console.

var contact = Person({name: "Bruce", gender: Person.Genders.Male, phoneNumber: "+1 240 776 2323"});  
console.log(contact.toString());  

First we define the Contact object:

if(!Contact) {  
  var Contact = function constructor(spec) {
    spec = spec || {};
    var that = {};
    that.phoneNumber = spec.phoneNumber;
    that.name = spec.name;
    that.toString = function() {
      return "Name: " + that.name + 
        "\nPhone: " + that.phoneNumber;
    };
    return that;
  };
}

Notice how there are phoneNumber, and name properties and a toString method. The constructor might have been called without an argument, so we define spec as an empty object in that case to avoid the dreaded Reference error: spec is not defined.

Now we will define the Person object to inherit from Contact.

if(!Person) {  
  var Person = function constructor(spec) {
    spec = spec || {};
    var static = constructor;
    static.Genders = {Male: 0, Female: 1};
    var that = Contact(spec);
    var base = {
      toString: that.toString
    };
    that.static = static;
    that.gender = spec.gender;
    that.toString = function() {
      var result = base.toString() + "\n";
      return result += "Gender: " + static.Genders.nameFor(that.gender);
    };
    return that;
  };
  Person();
}

Notice here how we are creating a variabled named static to be the contructor method itself, and we add a Genders property to it.

    var static = constructor;
    static.Genders = {Male: 0, Female: 1};

We create an instance of the base object; Contact, and then we create a private variable; base with the things we wish to override.

    var that = Contact(spec);
    var base = {
      toString: that.toString
    };

We also set the static property on our own object. That is convenient to be able to access static properties that way. The Java language has that feature too.

    that.static = static;

We set the gender property directly from the spec argument.

    that.gender = spec.gender;

Now it is time to implement the overriden toString method.

    that.toString = function() {
      var result = base.toString() + "\n";
      return result += "Gender: " + static.Genders.nameFor(that.gender);
    };

We call the base object's toString method first, and add a newline character, and then we add the gender. Notice how we call the nameFor method and pass the that.gender as argument.

The final thing to notice in the Person constructor is that we need to create at least one object to initialize the static properties.

  Person();

The nameFor method is generically useful, so we will add it to Object.prototype:

Object.prototype.nameFor = function(value) {  
  var property;
  for(property in this) {
    if(this[property] === value) {
      return property;
    }
  }
  return undefined;
};

It basically iterates over the properties of the object it was called on until it finds a property with the same value, and returns the name.

When we write

static.Genders.nameFor(that.gender);  

it returns either "Male", or "Female", or undefined if there were no matching values.