Ruby's Open Classes and Inheritance in JavaScript

Using the compact extend function to simulate class-based inheritance in JavaScript we have many of the same features of Ruby classes. One important feature is that classes remain open and that changes in the superclass are automatically also in the subclass. Through the extend function's natural chaining of prototypes we can have this open and inheritable changes. Below are the Ruby and JavaScript versions of the same example to show this at work.


class Person
  def initialize(first, last)
    @first = first
    @last = last

  def to_s
    @first + ' ' + @last

class Employee < Person
  def initialize(first, last, id)
    super(first, last)
    @id = id

  def to_s
    super + ': ' + @id.to_s

peter ='Peter', 'Michaux', 3)

puts peter # Peter Michaux: 3

# open the Person class and add a new method
class Person
  def reverse_name
    @last + ', ' + @first

puts peter.reverse_name  # Michaux, Peter


var Class = {
  extend: function(subclass, superclass) {
            function D() {}
            D.prototype = superclass.prototype;
            subclass.prototype = new D();
            subclass.prototype.constructor = subclass;
            subclass.superclass = superclass;
            subclass.superproto = superclass.prototype;

function Person(first, last) {
  this.first = first;
  this.last = last;

Person.prototype.toString = function() {
  return this.first + ' ' + this.last;

function Employee(first, last, id) {, first, last); = id;
Class.extend(Employee, Person);

Employee.prototype.toString = function() {
  return + ': ' +;

var peter = new Employee('Peter', 'Michaux', 3);

document.write(peter.toString()); // Peter Michaux: 3

// open the Person class and add a new method
Person.prototype.reverse_name = function() {
  return this.last + ', ' + this.first;

document.write(peter.reverse_name()); // Michaux, Peter

And now we have all of this nice Ruby-type behavior with only the same simple eight lines of code that gave us the ability to simulate Ruby's "super". This is just another strength of the extend function.

Although Prototype.js itself doesn't need class-based inheritance, part of that libraries goal is to somewhat simulate Ruby in JavaScript. By included the extend function Prototype.js users could have Ruby-style classes enabled through a very simple JavaScript function.


Have something to write? Comment on this article.