1

I'm trying to monkey patch a javascript Date constructor. I have the following code:

var __Date = window.Date;
window.Date = function(){
    __Date.apply(this, Array.prototype.slice.call(arguments));
};
window.Date.prototype = __Date.prototype;

As far as I know the javascript constructor (when called) does three things:

  1. It creates a new object that the this points to when the constructor function is executed
  2. It sets up this object to delegate to this constructor's prototype.
  3. It executes the constructor function in the context of this newly created object.

Ad.1 is accomplished automatically by the way that the new Date function will be called (new Date())

Ad.2 if accomplished by setting my new Date.prototype to be the original Date.prototype.

Ad.3 is accomplished by calling the original Date function in the context of the newly created object with the same paramters that are passed to "my" Date function.

Somehow it does not work. When i call e.g. new Date().getTime() i get an error saying that TypeError: this is not a Date object.

Why doesn't it work? Even this code:

new Date() instanceof __Date

returns true so by setting the same prototypes i fooled the instanceof operator.

PS. the whole point of this is that I want to check the arguments passed to the Date constructor and alter them when a certain condition is met.

kamilkp
  • 9,690
  • 6
  • 37
  • 56
  • 1
    "the whole point of this is that I want to check the arguments passed to the Date constructor and alter them when a certain condition is met." --- why don't you create a utility class that produces a `Date` instance then? – zerkms Mar 14 '14 at 09:01
  • 1
    I think you may be looking for http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible – elclanrs Mar 14 '14 at 09:03
  • @zerkms - because i want to create them by calling `new Date()` not any other syntax. – kamilkp Mar 14 '14 at 09:09
  • 2
    @kamilkp: it's bad from both design and maintainability perspective. 1. Because of prefer composition over inheritance 2. Because everyone would expect a native type to behave *exactly* as it is explained in ECMAScript specification. – zerkms Mar 14 '14 at 09:10
  • 1
    I agree that it might not be a best idea to actually do it. But the question was ***why*** dosn't work, and ***how*** to make it work – kamilkp Mar 14 '14 at 09:46

1 Answers1

0

Thanks to the link provided by @elclanrs I have come up with a working solution:

var __Date = window.Date;
window.Date = function f(){
    var args = Array.prototype.slice.call(arguments);
    // Date constructor monkey-patch to support date parsing from strings like
    // yyyy-mm-dd hh:mm:ss.mmm
    // yyyy-mm-dd hh:mm:ss
    // yyyy-mm-dd
    if(typeof args[0] === "string" && /^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2}(\.\d{3})?)?$/.test(args[0])){
        args[0] = args[0].replace(/-/g, '/').replace(/\.\d{3}$/, '');
    }
    args.unshift(window);
    if(this instanceof f)
        return new (Function.prototype.bind.apply(__Date, args));
    else
        return __Date.apply(window, args);
};
// define original Date's static properties parse and UTC and the prototype
window.Date.parse = __Date.parse;
window.Date.UTC = __Date.UTC;
window.Date.prototype = __Date.prototype;

Question still remains: why my first attempt didn't work?

kamilkp
  • 9,690
  • 6
  • 37
  • 56
  • I think this explains why, but I haven't groked it myself: http://nullprogram.com/blog/2013/03/24/. – Gui Prá Jun 30 '14 at 03:50