我有自己的jquery插件,用于使用MVC HtmlHelper扩展方法呈现的日期选择器控件。其日期格式为dd / mm / yyyy(澳大利亚日期)。
为了更容易从输入<input type=text .../>
构造一个javascript日期对象,我按如下方式覆盖了构造函数:
// Save the default constructor
var _DefaultDateConstructor = Date.prototype.constructor;
// Constructor
Date = function () {
var date = new _DefaultDateConstructor();
if (arguments === undefined || arguments.length === 0) {
// Ensure an invalid date is returned
date.setDate(Number.NaN);
return date;
}
// Get the arguments
var args = arguments[0].toString().split(/[\/ ]/);
// Set date properties
date.setMilliseconds(0);
date.setSeconds(0);
date.setMinutes(0);
date.setHours(0);
date.setDate(parseInt(args[0], 10));
date.setMonth(parseInt(args[1], 10) - 1);
date.setFullYear(parseInt(args[2], 10));
return date;
}
然后扩展原型
Date.prototype.isValid = function () {
return !isNaN(this.getTime());
}
Date.prototype.clone = function () {
return new _DefaultDateConstructor(this.getTime());
}
// More methods to return day name, month name etc. for formatting the display.
这允许我这样做:
this.selectedDate = new Date(this.input.val());
其中this.selectedDate
是我可以使用的有效javascript日期,this.input
会正确地回复给我的控制器。
在测试js文件中工作时,所有工作都按预期工作,但是当我将代码复制到插件文件中时,它全部崩溃并被烧毁。经过多次拔毛,我意识到我已经在方法之前切割并粘贴了构造函数。一旦我将构造函数放在方法之后(根据测试文件),它就会重新开始工作。
我的第一个问题是为什么我 undefined不是函数错误?当然(但显然不是!)被覆盖的构造函数返回一个javascript日期对象,因此如果在构造函数之后声明原型方法应该有效。
我的第二个相关问题是,是否有一种方法可以将重写的构造函数“私有”到插件中。如果加载插件并在控制台中输入myDate = new Date()
,它将返回Invalid Date
(这是我想要的插件),但会让插件的其他用户感到困惑。
答案 0 :(得分:7)
如果你想在插件中使用不同的行为,那么为什么不用你自己的构造函数继承Date
对象而不是替换Date()
构造函数当你想要不同的行为时使用那个构造函数。
因此,您保持Date()
构造函数不变,以便其他所有人都能获得正常的Date
行为。然后,当您想要特殊行为时,您将拥有自己的构造函数(称为ValidDate()
或任何您想要的)。
这是更正常的面向对象行为。当您想要派生/特殊行为时继承现有对象,同时仍保持原始对象不受影响以便正常使用。
此外,看起来您的构造函数只有在传递/
分隔的字符串时才有效。如果使用Date()
构造函数的任何其他形式的合法参数,例如您在.clone()
方法中使用的那些,那么您将尝试将其作为字符串处理。它看起来像你应该测试构造函数参数是否是一个字符串,只有它给它特殊处理。这样,其他合法构造函数参数(例如从另一个Date对象传入getTime()
结果)仍将继续有效。
以下是解决Date()
对象限制/奇怪问题的一种方法:
function ValidDate(a,b,c,d,e,f,g) {
var date;
if (arguments.length === 0) {
// your special behavior here
date = new Date();
}
else if (arguments.length === 1) {
if (typeof a === "string") {
// add your own constructor string parsing here
} else {
// normal default processing of single constructor argument
date = new Date(a);
}
} else {
// must be this form: new Date(year, month, day, hour, minute, second, millisecond);
// the picky Date() constructor doesn't handle undefined
// for an argument so we pass zero for any missing argument
c = c || 0;
d = d || 0;
e = e || 0;
f = f || 0;
g = g || 0;
date = new Date(a,b,c,d,e,f,g);
}
// add custom methods to this Date object
date.isValid = function() {
return !isNaN(this.getTime());
}
date.clone = function() {
return ValidDate(this.getTime());
}
return date;
}
答案 1 :(得分:2)
我的第一个问题是为什么我得到undefined不是函数错误?当然(但显然不是!)被覆盖的构造函数返回一个javascript日期对象,因此如果在构造函数之后声明原型方法应该有效。
如果首先覆盖构造函数,则将原型方法添加到新构造函数的原型中。但是构造函数本身返回一个常规的Date对象,它有一个不同的原型,没有那些方法。
我的第二个相关问题是,是否有一种方法可以将重写的构造函数“私有”到插件中。如果加载插件并在控制台中输入myDate = new Date(),它将返回Invalid Date(这是我想要的插件),但会让插件的另一个用户感到困惑。
不,没有。覆盖Date构造函数意味着覆盖全局变量。