On Github dilvie / fluent-prototypal-oo
"Those who are unaware they are walking in darkness will never seek the light."
~ Bruce Lee
How to Think in Prototypal OO
Eric Elliott
... but no class imitation has ever become a defacto standard.
Why is that?
"The problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana, but what you got was a gorilla holding the banana and the entire jungle."
~ Joe Armstrong, "Coders at Work"
For years I built apps in JavaScript, forgetting that these problems ever existed...
"Favor object composition over class inheritance."
~ The Gang of Four, "Design Patterns"
A working sample.
It's that simple.
function Greeter(name) {
  this.name = name || 'John Doe';
}
Greeter.prototype.hello = function hello() {
  return 'Hello, my name is ' + this.name;
}
var george = new Greeter('George');
var proto = {
  hello: function hello() {
    return 'Hello, my name is ' + this.name;
  }
};
var george = Object.create(proto);
george.name = 'George';
var proto = {
  hello: function hello() {
    return 'Hello, my name is ' + this.name;
  }
};
var george = _.extend({}, proto, {name: 'George'});
var foo = _.extend({
  attrs: {},
  set: function (name, value) {
    this.attrs[name] = value;
    this.trigger('change', {
      name: name,
      value: value
    });
  },
  get: function (name, value) {
    return this.attrs[name];
  }
}, Backbone.Events);
Can replace:
var model = function () {
  var attrs = {};
  this.set = function (name, value) {
    attrs[name] = value;
    this.trigger('change', {
      name: name,
      value: value
    });
  };
  this.get = function (name, value) {
    return attrs[name];
  };
  _.extend(this, Backbone.Events);
};
var george = {};
model.call(george).set('name', 'George');
george.get('name'); // 'George'
george.on('change', function (event) {
  console.log(event.name, event.value);
});
george.set('name', 'Simon'); // name Simon
Lots of hoop-jumping to use all these features together.
Create objects from reusable, composable behaviors.
Getting started (Node):
$ npm install stampit
Getting started (without Node):
$ git clone git://github.com/dilvie/stampit.git
var a = stampit().enclose(function () {
  // Secrets go here:
  var a = 'a';
  // Methods can access secrets.
  // Nothing else can.
  this.getA = function () {
    return a;
  };
});
a(); // Object -- so far so good. a().getA(); // "a"
var b = stampit().enclose(function () {
  // This var won't collide with the other `a`
  var a = 'b';
  this.getB = function () {
    return a;
  };
});
var c = stampit.compose(a, b); var foo = c(); // we won't throw this one away... foo.getA(); // "a" foo.getB(); // "b"
Can your class library do that?
ES6 class can't.
var availability = stampit().enclose(function () {
  var isOpen = false; // private
  return stampit.extend(this, {
    open: function open() {
      isOpen = true;
      return this;
    },
    close: function close() {
      isOpen = false;
      return this;
    },
    isOpen: function isOpenMethod() {
      return isOpen;
    }
  });
});
var membership = stampit({
    add: function (member) {
      this.members[member.name] = member;
      return this;
    },
    getMember: function (name) {
      return this.members[name];
    }
  },
  {
    members: {}
  });
var defaults = stampit().state({
    name: 'The Saloon',
    specials: 'Whisky, Gin, Tequila'
  });
"Favor object composition over class inheritance."
var bar = stampit.compose(defaults, availability, membership);
// Note that you can override state on instantiation:
var myBar = bar({name: 'Moe\'s'});
// Silly, but proves that everything is as it should be.
myBar.add({name: 'Homer' }).open().getMember('Homer');
“When there is freedom from mechanical conditioning, there is simplicity. The classical man is just a bundle of routine, ideas and tradition. If you follow the classical pattern, you are understanding the routine, the tradition, the shadow – you are not understanding yourself.”
~ Bruce Lee