我正在尝试子类化/扩展原生Date对象,而不修改原生对象本身。
我试过了:
var util = require('util');
function MyDate() {
Date.call(this);
}
util.inherits(MyDate, Date);
MyDate.prototype.doSomething = function() {
console.log('Doing something...');
};
var date = new MyDate();
date.doSomething();
console.log(date);
console.log(date.getHours());
还有这个:
function MyDate() {
}
MyDate.prototype = new Date();
MyDate.prototype.doSomething = function() {
console.log("DO");
}
var date = new MyDate();
date.doSomething();
console.log(date);
在这两种情况下,date.doSomething()
都可以工作,但当我调用任何本机方法(如date.getHours()
甚至console.log(date)
)时,都会得到“TypeError: this is not a Date object.‘”。
有什么想法吗?或者我坚持扩展顶级Date对象?
发布于 2011-05-21 01:11:50
查看date.js中的v8代码:
function DateGetHours() {
var t = DATE_VALUE(this);
if (NUMBER_IS_NAN(t)) return t;
return HOUR_FROM_TIME(LocalTimeNoCheck(t));
}
看起来DATE_VALUE是一个完成这项任务的宏:
DATE_VALUE(arg) = (%_ClassOf(arg) === 'Date' ? %_ValueOf(arg) : ThrowDateTypeError());
所以,看起来v8不会让你子类Date。
发布于 2015-06-17 12:36:23
这可以在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子类化的方法,因为Date()
构造函数会变魔术来设置内部[[Class]]
,而大多数date方法都需要设置它。这将在Node、IE 9+和几乎所有其他JS引擎中工作。
类似的方法也可以用于对Array进行子类化。
发布于 2015-04-15 23:22:13
在ES6中,可以子类化内置构造函数(Array
、Date
和Error
) - reference
问题是没有办法做到这一点与目前的ES5引擎,因为巴别塔indicates,将需要一个浏览器与原生ES6支持。
到目前为止(2015-04-15),当前用于子类化的ES6 browser support非常弱/不存在。
https://stackoverflow.com/questions/6075231
复制相似问题