metaclass
A class where its instances are classes
Usage
Exports one thing: The MetaClass
class.
MetaClass
takes two arguments: name
(a String
that is the name of the class) and prototype
(Which is the prototype of the returned class).
If you inherit from MetaClass
, the metaclasses prototype will act like static properties / methods for the created classes.
Most of the time you will want to create a subclass with more limited parameters (And create the prototype in the constructor of the metaclass).
/* Importing the module is done like this. // With modulesimport MetaClass from 'metaclass'; // In nodeconst MetaClass = require('metaclass'); // In browser// (Note: Use browser_metaclass.js as it will work and// trying to use Babel on metaclass.js will// lead to subtle bugs)<script src="/js/browser_metaclass.js"></script>const MetaClass = window.MetaClass;*/ const create_property = { return thisindex; } { thisindex = value; } enumerable: true configurable: true; /* For example, `NamedArray` * returns a class that inherits from * `Array` and also has named * getters and setters for indices. */ { const prototype = Object; if typeof index_names === 'string' || index_names instanceof String index_names = Stringindex_names; else index_names = Array; for let i = 0; i < index_nameslength; i++ Object; delete prototypeconstructor; supername prototype; this_index_names = index_names; } { const arr = ; for const name of this_index_names arrname = objname; return arr; } const Point = 'Point' 'x y'; { { return Math; } { return thisi * other0 + thisj * other1; }} // Used like thisconst origin = 0 0;const p = 2 3;console;// 0 0 2 2console;// 0 0 3 3 const vec = 3 4;const vec2 = Vector;console;// 3 5console;// 5 39 console; // trueconsole; // true
Theory
JavaScript classes are just functions. All functions are instances of Function
. Function
is a class that has a constructor.
MetaClass
extends Function
. When extending an object, you have to call super
, which invokes the constructor of the base class. The Function
constructor takes an argument list then the body of the function as a string (Kind of like eval
), except it is run in the global scope. This means that it is hard to access a closure object (Like the original constructor
function to initialise the new class). To solve this, a reference to the function being called is obtained using arguments.callee
, where the original constructor is in a property. Since MetaClass
objects are also instances of Function
, they can be called and be constructed with new
.
MetaClass
instances implement [[Call]]
, so their typeof
is defined by the standards to be function
.
All MetaClass
objects have the same function body. The only difference is the properties.