Skip to content

Instantly share code, notes, and snippets.

@ravinGit
Forked from jashkenas/minimalist-classes.js
Created November 17, 2012 07:23
Show Gist options
  • Save ravinGit/4094002 to your computer and use it in GitHub Desktop.
Save ravinGit/4094002 to your computer and use it in GitHub Desktop.
// Here is a proposal for minimalist JavaScript classes, humbly offered.
// There are (at least) two different directions in which classes can be steered.
// If we go for a wholly new semantics and implementation, then fancier classical
// inheritance can be supported with parallel prototype chains for true inheritance
// of properties at both the class and instance level.
// If however, we keep current JavaScript prototype semantics, and add a form that
// can desugar to ES3, things must necessarily stay simpler. This is the direction
// I'm assuming here.
// If we want to have static class bodies (no executable code at the top level),
// then we would do well to reuse the known and loved JavaScript idiom for
// fixed lists of properties -- the object literal.
// First, basic usage from a real-world library (Three.js)
class Color {
constructor: function(hex) {
...
},
r: 1, g: 1, b: 1,
copy: function(color) {
...
},
setRGB: function(r, g, b) {
...
},
setHSV: function(h, s, v) {
...
}
}
// To create a class with its prototype chain set correctly:
class Fox extends Animal {
...
}
// Note that "Animal" here is a class object (constructor function) in its
// own right. Fox.prototype is set to an instance of Animal that has been
// constructed without calling its constructor function -- this is the
// usual two-step setting-up-a-prototype shuffle.
// There is no special syntax for setting class-level properties, as they are
// relatively rare. Just add them to the class object itself:
Fox.CONSTANT = value;
// Note that the right-hand side of a class definition is just an expression,
// an object literal is not required. You can be fully dynamic when creating a
// class:
class Student objectContainingStudentProperties
// Or even:
class Protester merge(YoungAdult, WorkEthic, Idealism, {
student: true
})
// The point I'm trying to make being that the own properties of the right hand
// side, however they're derived, become the prototypal properties of the resulting
// class.
// Similarly, class definitions are themselves expressions, and anonymous classes
// are equally possible:
animals.push(class Fox {});
var subclass = function(parent) {
return class extends parent;
};
// Naturally, classes can be built up programmatically in this fashion.
var generateModelClass = function(columns) {
var definition = {};
columns.forEach(function(col) {
definition['get' + col] = function() {
return this[col];
};
definition['set' + col] = function(value) {
return this[col] = value;
};
});
return class definition;
};
// Finally, the Monster class from the current nutshell proposal
// (http://wiki.ecmascript.org/doku.php?id=harmony:classes#the_proposal_in_a_nutshell)
// ... sans unnecessary restrictions:
class Monster {
constructor: function(name, health) {
this.name = name;
this.health = health;
},
attack: function(target) {
log("The monster attacks " + target);
},
isAlive: function() {
return this.health > 0;
},
setHealth: function(value) {
if (value < 0) {
throw new Error("Health must be non-negative.");
}
this.health = value;
},
numAttacks: 0,
attackMessage: "The monster hits you!"
}
// I think that's about the run of it. Note what is left out: public / private /
// static / frozen / const properties and their ilk. Personally, I'm of the view
// that all of these modifiers are deeply undesirable in a language as dynamic
// as JavaScript and won't be much used, if added ... but I also think that
// getters and setters should be deprecated and removed.
// If public / private / static / frozen / const must be a part of class syntax
// in JS.next, then they must be valid prefixes for object literals as well --
// and can easily be used to define classes with those properties under this
// proposal.
// There are no new semantics here, and these classes can easily be transpiled
// into ES3 if needed -- just simpler declaration of constructors with prototypal
// properties and correctly configured prototype chains.
// tl;dr
// Classes are a new expression with the form ([] means optional):
// class [name] [extends parent] [expression]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment