覆盖javascript日期构造函数

时间:2014-05-09 04:03:07

标签: javascript jquery jquery-plugins

我有自己的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(这是我想要的插件),但会让插件的其他用户感到困惑。

2 个答案:

答案 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;
}

工作示例:http://jsfiddle.net/jfriend00/B25LX/

答案 1 :(得分:2)

  

我的第一个问题是为什么我得到undefined不是函数错误?当然(但显然不是!)被覆盖的构造函数返回一个javascript日期对象,因此如果在构造函数之后声明原型方法应该有效。

如果首先覆盖构造函数,则将原型方法添加到新构造函数的原型中。但是构造函数本身返回一个常规的Date对象,它有一个不同的原型,没有那些方法。

  

我的第二个相关问题是,是否有一种方法可以将重写的构造函数“私有”到插件中。如果加载插件并在控制台中输入myDate = new Date(),它将返回Invalid Date(这是我想要的插件),但会让插件的另一个用户感到困惑。

不,没有。覆盖Date构造函数意味着覆盖全局变量。