Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
var assert = require('assert')
, subclass = function(type, proto){
// make sure we are extending a global constructor
// accepted: [Boolean, Number, String, Array, Object, Function, RegExp, Date]
if(!global[type.name] || global[type.name].name != type.name) throw new Error();
var constructor = proto.constructor,
keys = Object.keys(proto),
Obj = process.binding('evals').Script.runInNewContext('x = '+type.name), // eval ftw
obj = function(){
var instance = new Obj();
if(constructor) constructor.apply(instance, arguments);
return instance;
};
obj.prototype.__proto__ = type.prototype; // passes instanceof 'type'
Obj.prototype.__proto__ = obj.prototype; // passes instanceof 'this'
for(var i=0,l=keys.length; i<l; i++){
if(keys[i] != 'constructor') Obj.prototype[keys[i]] = proto[keys[i]];
}
return obj;
}
, SpecialArray = subclass(Array, {
constructor: function(){
Object.defineProperty(this, 'special', {
value: 'special',
enumerable: false
});
},
test: function(){}
})
, arr = []
, sa = new SpecialArray();
// very strict, instance constructor === Array.constructor
assert.ok(Array.isArray(sa));
// still passes instanceof Array tests
assert.ok(sa instanceof Array);
// still has unique identity
assert.ok(sa instanceof SpecialArray);
// should be extended
assert.ok(typeof sa.test == 'function');
// this should not
assert.ok(typeof arr.test == 'undefined');
// pass other hardcore type checks
assert.ok(Object.prototype.toString.call(sa) == '[object Array]');
// make sure constructor works
assert.ok(sa.special == 'special');
assert.ok(sa.propertyIsEnumerable('special') == false);
// make sure length property still works
assert.ok(sa.push(1,2,3) == 3);
assert.ok(sa.push(4,5) == 5);
assert.ok(sa.length == 5);
// check JSON.stringify()
assert.ok(JSON.stringify(sa) == '[1,2,3,4,5]');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.