1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | enyo.kind = function(inProps) { // kind-name to constructor map could be faulty now that a new kind exists, so we simply destroy the memoizations enyo._kindCtors = {}; // extract 'name' property var name = inProps.name || ""; // extract 'kind' property var kind = inProps.isa || inProps.kind; // if we have an explicit kind property that is undefined, we probably tried // to reference an kind that is not yet in scope if ((kind === undefined) && ("kind" in inProps)) { throw "enyo.kind: Attempt to subclass an 'undefined' kind. Check dependencies for [" + name + "]."; } // establish base class reference var base = kind && enyo.constructorForKind(kind); var isa = base && base.prototype || null; // make a boilerplate constructor var ctor = enyo.kind.makeCtor(); delete inProps.name; // semi-reserved word 'constructor' causes problems with Prototype and IE, so we rename it here if (inProps.hasOwnProperty("constructor")) { inProps._constructor = inProps.constructor; delete inProps.constructor; } // create our prototype //ctor.prototype = isa ? enyo.delegate(isa) : {}; enyo.setPrototype(ctor, isa ? enyo.delegate(isa) : {}); // put in our props enyo.mixin(ctor.prototype, inProps); // alias class name as 'kind' in the prototype ctor.prototype.kindName = name; // cache super-class constructor ctor.prototype.base = base; // reference our real constructor ctor.prototype.ctor = ctor; // support pluggable 'features' enyo.forEach(enyo.kind.features, function(fn){ fn(ctor, inProps); }); // put reference into namespace enyo.setObject(name, ctor); return ctor; }; |
kernel/Oop.js
enyo.kind
enyo.kind: function(inProps)
Creates a JavaScript constructor function with a prototype defined by inProps.
enyo.kind makes it easy to build a constructor-with-prototype (like a class) that has advanced features like prototype-chaining (inheritance).
A plug-in system is included for extending the abilities of the kind generator, and constructors are allowed to perform custom operations when subclassed.
Special Property Names
Generally the properties defined in inProps are copied directly to the generated prototype, but certain property names trigger special processing.
Examples of special properties are:
name: the name property defines the name of the created constructor in the global namespace (intermediate objects are created automatically). name is not copied directly to the prototype, but is instead stored as kindName.
1 2 3 4 5 6 7 8 9 | // Creates a function MyNamespace.MyKind with a prototype. // MyNamespace.MyKind.prototype.kindName is set to "MyNamespace.MyKind". // MyNamespace.MyKind.prototype.plainProperty is set to "foo". enyo.kind({ name: "MyNamespace.MyKind" plainProperty: "foo" }); // Make an instance of the new kind var myk = new MyNamespace.MyKind(); |
kind: the name of or reference to a kind to derive from, like a super-class. The new constructor’s prototype is chained to the prototype specified by kind, and the base property in the new prototype is set to reference the kind constructor.
1 2 3 4 5 6 7 | // Create a function MyKind with a prototype, derived from enyo.Object. // MyKind.prototype.kindName is set to "MyKind". // MyKind.prototype.base is set to enyo.Object. enyo.kind({ name: "MyKind", kind: enyo.Object }); |
constructor: a function to call when a new instance is created. Actually stored on the prototype as _constructor.
1 2 3 4 5 6 7 8 9 10 11 | // Create a function MyKind with a prototype, derived from enyo.Object. // _constructor_ is called when an instance is created. enyo.kind({ name: "MyKind", kind: enyo.Object, constructor: function() { this.instanceArray = []; // call the constructor inherited from Object this.inherited(arguments); } }); |
statics: properties from any statics object are copied onto the constructor directly, instead of the prototype.
1 2 3 4 5 6 7 8 9 10 11 | // Create a kind with a static method. enyo.kind({ name: "MyKind", statics: { info: function() { return "MyKind is a kind with statics."; } } }); // invoke the static info() method of MyKind console.log(MyKind.info()); |
Certain kinds in the framework define their own special properties. For example, see the published property supported by enyo.Object.
inherited
The inherited feature allows you to easily call the super-kind method for any method that has been overridden.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | enyo.kind({ name: "MyKind", doWork: function() { this.work++; } }); enyo.kind({ name: "MyDerivedKind", kind: "MyKind", doWork: function() { if (this.shouldDoWork) { this.inherited(arguments); } } }); |
The first argument to inherited is required to be the literal arguments, which is a special JavaScript variable that contains information about the executing function.