JavaScript:重写Date.prototype.constructor
我想更改标准日期对象的行为。传递给构造函数的JavaScript:重写Date.prototype.constructor,javascript,date,constructor,prototype,Javascript,Date,Constructor,Prototype,我想更改标准日期对象的行为。传递给构造函数的0..99之间的年份应解释为fullYear(没有添加1900)。但是我下面的函数不起作用 var oDateConst = Date.prototype.constructor; // save old contructor Date.prototype.constructor = function () { var d = oDateConst.apply(oDateConst, arguments); // create object
0..99
之间的年份应解释为fullYear
(没有添加1900
)。但是我下面的函数不起作用
var oDateConst = Date.prototype.constructor; // save old contructor
Date.prototype.constructor = function () {
var d = oDateConst.apply(oDateConst, arguments); // create object with it
if ( ((arguments.length == 3) || (arguments.length == 6))
&& ((arguments[0] < 100) && (arguments[0] >= 0))) {
d.setFullYear(arguments[0]);
}
return d;
}
var oDateConst=Date.prototype.constructor;//拯救老承包商
Date.prototype.constructor=函数(){
var d=oDateConst.apply(oDateConst,参数);//使用它创建对象
if(((arguments.length==3)| |(arguments.length==6))
&&((参数[0]<100)和&(参数[0]>=0))){
d、 setFullYear(参数[0]);
}
返回d;
}
为什么从来没有人打过电话?您将如何解决此问题?它从未被调用的原因是您在
Date.prototype
上更改了constructor
属性。但是,您可能仍在使用代码newdate()
创建日期。所以它从不使用构造函数。您真正想做的是创建自己的日期构造函数:
function MyDate() {
var d = Date.apply(Date, arguments);
if ((arguments.length == 3 || arguments.length == 6)
&& (arguments[0] < 100 && arguments[0] >= 0)) {
d.setFullYear(arguments[0]);
return d;
}
function myDate() {
var date = instantiate(Date, arguments);
var args = arguments.length;
var arg = arguments[0];
if ((args === 3 || args == 6) && arg < 100 && arg >= 0)
date.setFullYear(arg);
return date;
}
编辑:而不是使用Date.apply
我宁愿使用以下实例化
函数,该函数允许您:
以下是我将如何实现新的日期构造函数:
function MyDate() {
var d = Date.apply(Date, arguments);
if ((arguments.length == 3 || arguments.length == 6)
&& (arguments[0] < 100 && arguments[0] >= 0)) {
d.setFullYear(arguments[0]);
return d;
}
function myDate() {
var date = instantiate(Date, arguments);
var args = arguments.length;
var arg = arguments[0];
if ((args === 3 || args == 6) && arg < 100 && arg >= 0)
date.setFullYear(arg);
return date;
}
函数myDate(){
变量日期=实例化(日期、参数);
var args=arguments.length;
var arg=参数[0];
如果((args==3 | | args==6)和&arg<100&&arg>=0)
日期。设置完整年份(arg);
返回日期;
}
编辑:如果要覆盖本机日期构造函数,则必须执行以下操作:
var d = MyDate();
Date = function (Date) {
MyDate.prototype = Date.prototype;
return MyDate;
function MyDate() {
var date = instantiate(Date, arguments);
var args = arguments.length;
var arg = arguments[0];
if ((args === 3 || args == 6) && arg < 100 && arg >= 0)
date.setFullYear(arg);
return date;
}
}(Date);
Date=函数(日期){
MyDate.prototype=Date.prototype;
返回MyDate;
函数MyDate(){
变量日期=实例化(日期、参数);
var args=arguments.length;
var arg=参数[0];
如果((args==3 | | args==6)和&arg<100&&arg>=0)
日期。设置完整年份(arg);
返回日期;
}
}(日期);
借助Aadit M Shah的原生日期构造函数重写-这应该是一个回答,但我没有足够的SO rep来实现-正如@sakthi提到的,这样做会丢失原生日期方法。这有点糟糕,因为Date方法是不可枚举的,所以您必须对它们进行一些修改才能克隆它们
首先,我建议不要这样做,除非你必须这样做。在我的例子中,我在一个应用程序中使用了一堆遗留代码,这些代码使用格式“m-d-yyyy”构建日期,该格式在chrome中有效,但在safari中无效。我不能只在应用程序中进行查找/替换,因为有很多实例是从服务层或数据库中提取日期字符串的。因此,我决定在有“m-d-yyy”格式的datestring参数的情况下重写日期构造函数。我希望它尽可能的微创,这样它就可以作为一个正常的约会
这里是我的更改-它应该允许您通过对构造函数的一些更改来覆盖date,但其他所有更改都是相同的。您需要在调用instantiate以执行您希望构造函数处理的任何操作之前更改MyDate构造函数。这将在应用系统日期构造函数之前发生
var bind = Function.bind;
var unbind = bind.bind(bind);
function instantiate(constructor, args) {
return new (unbind(constructor, null).apply(null, args));
}
Date = function (Date) {
// copy date methods - this is a pain in the butt because they're mostly nonenumerable
// Get all own props, even nonenumerable ones
var names = Object.getOwnPropertyNames(Date);
// Loop through them
for (var i = 0; i < names.length; i++) {
// Skip props already in the MyDate object
if (names[i] in MyDate) continue;
// Get property description from o
var desc = Object.getOwnPropertyDescriptor(Date, names[i]);
// Use it to create property on MyDate
Object.defineProperty(MyDate, names[i], desc);
}
return MyDate;
function MyDate() {
// we only care about modifying the constructor if a datestring is passed in
if (arguments.length === 1 && typeof (arguments[0]) === 'string') {
// if you're adding other date transformations, add them here
// match dates of format m-d-yyyy and convert them to cross-browser-friendly m/d/yyyy
var mdyyyyDashRegex = /(\d{1,2})-(\d{1,2})-(\d{4})/g;
arguments[0] = arguments[0].replace(mdyyyyDashRegex, function (match, p1, p2, p3) {
return p1 + "/" + p2 + "/" + p3;
});
}
// call the original Date constructor with whatever arguments are passed in here
var date = instantiate(Date, arguments);
return date;
}
}(Date);
var bind=Function.bind;
var unbind=bind.bind(bind);
函数实例化(构造函数、参数){
返回new(取消绑定(构造函数,null).apply(null,args));
}
日期=功能(日期){
//复制日期方法-这是一个痛苦的屁股,因为它们大多是不可数的
//拥有所有自己的道具,即使是不可计算的道具
var name=Object.getOwnPropertyNames(日期);
//循环通过它们
对于(var i=0;i
参考资料:
- (本帖)
typeof Date() == typeof new Date() //Should be false, but it returns true
在遗留项目中,上述场景可能会打破一些场景。除了上述内容和Dan Hlavenka指出的内容外,我同意这是迄今为止最完整的解决方案。这里是一个非常灵活的解决方案。它(我相信)处理所有不同的情况 DateStub-允许删除日期函数。
如果你有 '新日期(…)…'散布在你的代码中, 你想测试它,这是给你的。 它也适用于“时刻”
/**
* DateStub - Allows for stubbing out the Date function. If you have
* 'new Date(...)....' sprinkled throughout your code,
* and you want to test it, this is for you.
*
* @param {string} arguments Provide 0 to any number of dates in string format.
*
* @return a date object corresponding to the arguments passed in.
* If you pass only one date in, this will be used by all 'new Date()' calls.
* This also provides support for 'Date.UTC()', 'Date.now()', 'Date.parse()'.
* Also, this works with the moments library.
*
* Examples:
{ // Test with 1 argument
Date = DateStub('1/2/2033'); // Override 'Date'
expect(new Date().toString())
.toEqual('Sun Jan 02 2033 00:00:00 GMT-0500 (EST)');
expect(new Date().toString())
.toEqual('Sun Jan 02 2033 00:00:00 GMT-0500 (EST)');
Date = DateStub.JavaScriptDate; // Reset 'Date'
}
{ // Call subsequent arguments, each time 'new Date()' is called
Date = DateStub('1/2/1111', '1/2/1222'
, '1/2/3333', '1/2/4444'); // Override 'Date'
expect(new Date().toString())
.toEqual('Mon Jan 02 1111 00:00:00 GMT-0500 (EST)');
expect(new Date().toString())
.toEqual('Sun Jan 02 1222 00:00:00 GMT-0500 (EST)');
expect(new Date().toString())
.toEqual('Fri Jan 02 3333 00:00:00 GMT-0500 (EST)');
expect(new Date().toString())
.toEqual('Sat Jan 02 4444 00:00:00 GMT-0500 (EST)');
Date = DateStub.JavaScriptDate; // Reset 'Date'
}
{ // Test 'Date.now()'. You can also use: 'Date.UTC()', 'Date.parse()'
Date = DateStub('1/2/2033');
expect(new Date(Date.now()).toString())
.toEqual('Sun Jan 02 2033 00:00:00 GMT-0500 (EST)');
Date = DateStub.JavaScriptDate; // Reset 'Date'
}
*
* For more info: AAkcasu@gmail.com
*/
const DateStub =
function () {
function CustomDate(date) {
if (!!date) { return new DateStub.JavaScriptDate(date); }
return getNextDate();
};
function getNextDate() {
return dates[index >= length ? index - 1 : index++];
};
if (Date.name === 'Date') {
DateStub.prototype = Date.prototype;
DateStub.JavaScriptDate = Date;
// Add Date.* methods.
CustomDate.UTC = Date.UTC;
CustomDate.parse = Date.parse;
CustomDate.now = getNextDate;
}
var dateArguments = (arguments.length === 0)
? [(new DateStub.JavaScriptDate()).toString()] : arguments
, length = dateArguments.length
, index = 0
, dates = [];
for (var i = 0; i < length; i++) {
dates.push(new DateStub.JavaScriptDate(dateArguments[i]));
}
return CustomDate;
};
module.exports = DateStub;
// If you have a test file, and are using node:
// Add this to the top: const DateStub = require('./DateStub');
/**
*DateStub-允许删除日期函数。如果你有
*“新日期(…)…”散布在您的代码中,
*你想测试它,这是给你的。
*
*@param{string}参数以字符串格式提供0到任意数量的日期。
*
*@返回日期对象