Это можно сделать в ES5.Требуется непосредственное изменение цепочки прототипов.Это делается с помощью __proto__
или Object.setPrototypeOf()
.Я использую __proto__
в примере кода, поскольку он наиболее широко поддерживается (хотя стандартом является 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';
};
Хитрость заключается в том, что мы фактически создаем экземпляр объекта Date
(справильное количество аргументов), что дает нам объект с его внутренним [[Class]]
, установленным правильно.Затем мы модифицируем цепочку прототипов, чтобы сделать ее экземпляром XDate.
Итак, мы можем проверить все это, выполнив:
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)
Это единственный известный мне способ подкласса датыпотому что конструктор Date()
делает некоторую магию для установки внутреннего [[Class]]
, и большинство методов даты требуют его установки.Это будет работать в Node, IE 9+ и почти во всех других движках JS.
Аналогичный подход можно использовать для создания подклассов Array.