UNPKG

prototypal

Version:
175 lines (146 loc) 4.84 kB
Class ========== This is the result of a "_tour de force_" out of 4 blog posts about [ECMAScript 5 Descriptors](http://webreflection.blogspot.com/2014/03/what-books-wont-tell-you-about-es5.html) and probably the most compatible `Class` solution entirely based on ES5 Standards you can find these days. It has been simplified as much as possible and it's a lightweight replacement for an older [redefine.js](https://github.com/WebReflection/redefine#redefinejs) proposal, solving in its core a lot of problems that older, as well as modern Desktop or Mobile browsers, introduced in these days web development. ### prototypal.Class The **API** is straight forward, `Class({ .. properties .. })` or `Class(extend, { .. properties .. })`, where `extend` can be either `null`, any `object`, or simply a `Function` where in latter case its prototype will be automatically used to chain inheritance. ```javascript // a Null class example var Null = Class(null, {}); var n = new Null; n instanceof Object; // false // a generic class example var Rectangle = Class({ // constructor constructor: function (width, height) { this.width = width; this.height = height; }, // some method toString: function () { return '[object Rectangle]'; }, // default properties width: 0, height: 0, // a simple getter to retrieve the area area: Class.descriptor({ get: function () { return this.width * this.height; } }) }); // a generic extend example var Square = Class( Rectangle, { constructor: function (size) { Rectangle.call(this, size, size); }, toString: function () { return '[object Square]'; } }); var s = new Square(3); s.area; // 9 '' + s; // [object Square] ``` ### About Descriptors By default, all properties are the same as those found in native JavaScript _classes_ ```javascript // example of native descriptor Object.getOwnPropertyDescriptor( Object.prototype, 'toString' ); { value: [Function: toString], writable: true, enumerable: false, configurable: true } ``` These settings avoid any sort of problems when it comes to inherited defaults, as well as overwritten methods. #### Class.descriptor({ .. ES5 descriptor .. }) In case any other descriptor is needed, the `Class` offers an easy way do define exactly the needed one: ```javascript // based on previous example var Rectangle = Class({ // ... code as seen before ... // specifying a descriptor as // enumerable: false // configurable: false // get: function () { ... } area: Class.descriptor({ get: function () { return this.width * this.height; } }) }); ``` #### Class.lazy(callback) `lazy` is useful to set a property once avoiding expensive computations or, as example, creating maybe not always needed extra objects, preserving performance, CPU, and allocated RAM. ```javascript var Person = Class({ constructor: function (parents) { this.parents = parents; }, // here an example of .. // . something maybe not needed right on // . something not always accessed // . something expensive to compute // once computed there is no need // to compute it again so it should // rather be a property than a method genealogicTree: Class.lazy(function() { var p = this.parents, mom = p[0], dad = p[1], tree = { mom: [mom], dad: [dad] }; p = mom; while (p = p.parents) { tree.mom.push( p[0].genealogicTree, p[1].genealogicTree ); } p = dad; while (p = p.parents) { tree.dad.push( p[0].genealogicTree, p[1].genealogicTree ); } // returning the object that // will be set as // non writable // but configurable return tree; }) }); ``` Being configurable, whenever there is a need to recalculate the property it's still possible to `delete me.genealogicTree` and retrieve it again. #### Class.bound(callback) This is a simple internal `lazy` based hook able to automatically bind a method the very first time is accessed. ```javascript var MouseHandler = Class({ onClick: Class.bound(function (evt) { evt.preventDefault(); alert(this instanceof MouseHandler); // true }) }); var mh = new MouseHandler; document.body.addEventListener('click', mh.onClick); ``` ### Compatibility If your browser is not in this list, feel free to [test online](http://webreflection.github.io/prototypal/test/) and verify it's green. **Browsers** * Opera Desktop, Opera Mobile, and Opera Mini if using [es5-shim and es5-sham](./test/es5.js) upfront * WebKit Android 2+ * IE9 Desktop or Mobile and above * Kindle Fire Silk * webOS 2 * Firefox and Firefox Mobile or FirefoxOS * Chrome * Safari and Safari Mobile in iOS5+ * UC Browser * Nokia Xpress (Asha and WP)