evi*_*ery 22 javascript inheritance date node.js
我正在尝试子类化/扩展本机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());
Run Code Online (Sandbox Code Playgroud)
还有这个:
function MyDate() {
}
MyDate.prototype = new Date();
MyDate.prototype.doSomething = function() {
console.log("DO");
}
var date = new MyDate();
date.doSomething();
console.log(date);
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,date.doSomething()
工作,但当我调用任何本地方法,如date.getHours()
甚至console.log(date)
,我得到'TypeError:这不是一个Date对象.
有任何想法吗?还是我坚持扩展顶级Date对象?
Geo*_*ell 19
查看v8代码,在date.js中:
function DateGetHours() {
var t = DATE_VALUE(this);
if (NUMBER_IS_NAN(t)) return t;
return HOUR_FROM_TIME(LocalTimeNoCheck(t));
}
Run Code Online (Sandbox Code Playgroud)
看起来像DATE_VALUE是一个执行此操作的宏:
DATE_VALUE(arg) = (%_ClassOf(arg) === 'Date' ? %_ValueOf(arg) : ThrowDateTypeError());
Run Code Online (Sandbox Code Playgroud)
所以,似乎v8不会让你继承Date.
具体来看日期的MDC文档:
注意:请注意,Date对象只能通过调用Date或将其用作构造函数来实例化; 与其他JavaScript对象类型不同,Date对象没有文字语法.
看起来这个Date
对象根本就不是JS对象.当我写一个扩展库时,我最终做了以下事情:
function MyDate() {
var _d=new Date();
function init(that) {
var i;
var which=['getDate','getDay','getFullYear','getHours',/*...*/,'toString'];
for (i=0;i<which.length;i++) {
that[which[i]]=_d[which[i]];
}
}
init(this);
this.doSomething=function() {
console.log("DO");
}
}
Run Code Online (Sandbox Code Playgroud)
至少我先做了那个.最后JS Date对象的局限性让我变得更好,我改用自己的数据存储方法(例如,为什么getDate
=一年中的某一天?)
这可以在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';
};
Run Code Online (Sandbox Code Playgroud)
诀窍是我们实际实例化一个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)
Run Code Online (Sandbox Code Playgroud)
这是我知道子类日期的唯一方法,因为Date()
构造函数做了一些魔术来设置内部[[Class]]
和大多数日期方法需要设置.这将适用于Node,IE 9+和几乎所有其他JS引擎.
类似的方法可用于子类化Array.