-
-
Save Gozala/7e649e8c33d412e90178 to your computer and use it in GitHub Desktop.
Alternative sugar for classes in ES.next
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var _target = '[[target]]'; | |
var _name = '[[name]]'; | |
var _this = '[[this]]'; | |
Function.prototype.extend = function extend(properties) { | |
var prototype = Object.create(this.prototype); | |
Object.getOwnPropertyNames(properties).forEach(function(name) { | |
var desc = Object.getOwnPropertyDescriptor(properties, name); | |
var wrappedDesc = wrapDescriptor(desc, name, prototype); | |
Object.defineProperty(prototype, name, wrappedDesc); | |
}); | |
var constructor = prototype.constructor; | |
constructor.__proto__ = this; | |
constructor.prototype = prototype; | |
return constructor; | |
} | |
function wrapDescriptor(descriptor, name, prototype) { | |
var wrapped = {}; | |
if ('writable' in descriptor) | |
wrapped.writable = descriptor.writable; | |
if ('enumerable' in descriptor) | |
wrapped.enumerable = descriptor.enumerable; | |
if ('configurable' in descriptor) | |
wrapped.configurable = descriptor.configurable; | |
if ('value' in descriptor) { | |
wrapped.value = typeof descriptor.value !== 'function' ? descriptor.value : | |
wrap(descriptor.value, name, prototype) | |
} | |
if ('get' in descriptor) | |
wrapped.get = wrap(descriptor.get, name, prototype) | |
if ('set' in descriptor) | |
wrapped.set = wrap(descriptor.set, name, prototype) | |
return wrapped; | |
} | |
function wrap(unwrapped, name, prototype) { | |
var source = unwrapped.toString(); | |
// We use `eval` just to preserve `.length` and `.name` of unwrapped function. | |
return eval('(' + source.substr(0, source.indexOf('{')) + '{' + | |
' unwrapped[_this] = this; ' + | |
' unwrapped[_target] = prototype; ' + | |
' unwrapped[_name] = name; ' + | |
' var value = unwrapped.apply(this, arguments); ' + | |
' delete unwrapped[_this]; ' + | |
' delete unwrapped[_target]; ' + | |
' delete unwrapped[_name]; ' + | |
' return value; ' + | |
' })'); | |
} | |
function base() { | |
// constructor that called method (Super.caller is a function that actual | |
// constructor delegates to so we need to get it's caller to get to an actual | |
// constructor. | |
var caller = base.caller; | |
var target = caller[_target]; | |
var name = caller[_name]; | |
var self = caller[_this] | |
console.log(Caller = caller); | |
// We assume that `this` pseudo-variable is either passed via `call`, `apply` | |
// either it is passed implicitly in such case it matches value of `this` | |
// pseudo variables the `constructor`. | |
return Object.getPrototypeOf(target)[name].apply(self, arguments); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Point = Object.extend({ | |
constructor: function Point(options) { | |
this.x = options.x; | |
this.y = options.y; | |
}, | |
serialize: function() { | |
return this.x + ':' + this.y; | |
} | |
}); | |
Point.new = function() { | |
var instance = Object.create(this.prototype); | |
this.apply(instance, arguments); | |
return instance; | |
} | |
var p1 = new Point({ x: 10, y: 15 }); | |
p1.serialize() // "10:15" | |
var p2 = Point.new({ x: 2, y: 4 }); | |
p2.serialize() // "2:4" | |
var Pixel = Point.extend({ | |
constructor: function Pixel(options) { | |
base(options) | |
this.color = options.color | |
}, | |
serialize: function () { | |
return this.color + '@' + base() | |
} | |
}); | |
var px1 = new Pixel({ x: 0, y: 10, color: '#fff' }); | |
px1.serialize(); // "#fff@0:10" | |
var px2 = Pixel.new({ x: 17, y: 19, color: 'red' }); | |
px2.serialize(); // red@17:19 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment