2

jQuery Datepicker widget is based on built-in Date. I am trying to override Date to calculate our own calendar that has different year, month .... (without having to change datepicker code). I tried the below code for testing, but this override is being called twice.

Date.prototype.getFullYear = (function(){
    var $gfy = Date.prototype.getFullYear;
    if (!this.done) {
        this.done = true; // add my own variable to this instance
        return function() {
             return $gfy.call(this)+150;
       };
    } else {
        return function() {
             return $gfy.call(this);
        };
    }
}());

So,

  1. what is the correct way to override native functions and

  2. how do I add a variable to the original instance.

  3. how to get hold of the instance itself (this does not work here).

CraigTeegarden
  • 8,173
  • 8
  • 38
  • 43
alsaleem
  • 23
  • 3

1 Answers1

1

Some important distinctions first (you may already know this, but just so we're on the same page).

prototype changes the behavior of all objects (instances and future instances). So tread lightly when modifying built in types (Date, String, etc.) as you'll be changing the behavior of these objects for every routine that is using them.

Live Demo

//Add a property to the instance
var date = new Date(); 
date.newProp = 'test'; 
alert(date.newProp); //test

//----VS----

//Add a property to all instances existing 
//and too be created
Date.prototype.newProp2 = 'new prop'; 

var date2 = new Date(); 
alert(date2.newProp);//undefined 
alert(date2.newProp2); //new prop

//See how the prototype modified the existing instance as well. 
alert(date.newProp2); //new  prop

To answer your specific questions:

  1. It looks like you are overridding the native function correctly. Storing a copy of the native function so you can call it like a base function.
  2. From my example above, you'll either need to modify all Date instances or just the one in question.
    • var date = new Date(); date.done = false;
    • Date.prototype.done = false;
  3. The reason this doesn't work in your outer function is because it is a self executing anonymous function and is executed immediately in order to assign one of your inner functions to the getFullYear method.

All in all I'm not sure your approach is the best idea due to the danger of interfering with other libraries, and I'm not sure why you'd only want this function to return +150 a single time per Date instance, but here is your code modified to perform your intended logic.

Live Demo

//Add a variable to all Date objects
Date.prototype.done = false; 

//Override the getFullYear function
Date.prototype.getFullYear = (function(){

    //Store a reference to the native function
    var $gfy = Date.prototype.getFullYear;
    return function(){

        //Have we hit this routine before?
        if (!this.done) {

            //We've hit this routine once so flag it.
            this.done = true;

            //Execute native funciton, then add 150
            return $gfy.call(this)+150;
        } else {

            //Call the native function from now on.
            return $gfy.call(this);
        }
    }
}());//self executing function so it executes as soon as it is evaluated.

var date = new Date(); 

//Will return +150 the first time
alert(date.getFullYear()); 

//After that execute the default 
//function for'getFullYear'
alert(date.getFullYear()); 
Community
  • 1
  • 1
Brandon Boone
  • 16,281
  • 4
  • 73
  • 100
  • thanks for the explaination. 'this', per your statement, refers to the function while I wanted to get that instance (done with 'new'). User may instantiate many Date classes with different initial dates. Note : my intention was to do further calculation based on the instance's year (not just +150). – alsaleem Apr 14 '13 at 18:08