js覆盖函数被调用两次

时间:2013-04-14 14:33:57

标签: javascript override

jQuery Datepicker小部件基于内置日期。我试图覆盖日期来计算我们自己的日历,它有不同的年,月....(无需更改datepicker代码)。我尝试了下面的代码进行测试,但是这个覆盖被调用了两次。

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);
        };
    }
}());

所以,

  1. 覆盖原生函数的正确方法是什么?

  2. 如何将变量添加到原始实例。

  3. 如何掌握实例本身(这在这里不起作用)。

1 个答案:

答案 0 :(得分:1)

首先要有一些重要的区别(你可能已经知道了这一点,但我们只是在同一页面上)。

prototype更改所有对象(实例和将来的实例)的行为。因此,在修改内置类型(日期,字符串等)时要轻松一点,因为您将为使用它们的每个例程更改这些对象的行为。

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

回答您的具体问题:

  1. 看起来你正确地覆盖了原生函数。存储本机函数的副本,以便您可以像base函数一样调用它。
  2. 从上面的示例中,您需要修改所有Date实例或仅修改相关的实例。
    • var date = new Date(); date.done = false;
    • Date.prototype.done = false;
  3. this在您的外部函数中不起作用的原因是因为它是self executing anonymous function并且会立即执行,以便将您的一个内部函数分配给getFullYear方法。
  4. 总而言之,由于存在干扰其他库的危险,我不确定你的方法是最好的主意,而且我不确定为什么你只希望这个函数每个日期一次返回+150实例,但这里是您修改的代码,以执行您的预期逻辑。

    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());