I\'m trying to subclass/extend the native Date object, without modifying the native object itself.
I\'ve tried this:
var util = require(\'util\')
This can be done in ES5. It requires modifying the prototype chain directly. This is done using __proto__ or Object.setPrototypeOf(). I'm using __proto__ in the sample code since that's most widely supported (although the standard is Object.setPrototypeOf).
function XDate(a, b, c, d, e, f, g) {
var x;
switch (arguments.length) {
case 0:
x = new Date();
break;
case 1:
x = new Date(a);
break;
case 2:
x = new Date(a, b);
break;
case 3:
x = new Date(a, b, c);
break;
case 4:
x = new Date(a, b, c, d);
break;
case 5:
x = new Date(a, b, c, d, e);
break;
case 6:
x = new Date(a, b, c, d, e, f);
break;
default:
x = new Date(a, b, c, d, e, f, g);
}
x.__proto__ = XDate.prototype;
return x;
}
XDate.prototype.__proto__ = Date.prototype;
XDate.prototype.foo = function() {
return 'bar';
};
The trick is that we actually instantiate a Date object (with the correct number of arguments) which gives us an object with it's internal [[Class]] set correctly. Then we modify it's prototype chain to make it an instance of XDate.
So, we can verify all this by doing:
var date = new XDate(2015, 5, 18)
console.log(date instanceof Date) //true
console.log(date instanceof XDate) //true
console.log(Object.prototype.toString.call(date)) //[object Date]
console.log(date.foo()) //bar
console.log('' + date) //Thu Jun 18 2015 00:00:00 GMT-0700 (PDT)
This is the only way I know of to subclass date because the Date() constructor does some magic to set the internal [[Class]] and most date methods require that to be set. This will work in Node, IE 9+ and almost all other JS engines.
Similar approach can be used for subclassing Array.