代码之家  ›  专栏  ›  技术社区  ›  Peter McG

简单的JavaScript String.replace.call会导致“InternalError:递归太多”

  •  2
  • Peter McG  · 技术社区  · 15 年前

    给定以下JavaScript“类”定义:

    var Quota = function(totalMinutes){
        this.totalMinutes = parseInt(totalMinutes || 0, 10);
    };
    
    Quota.prototype.valueOf = function(){
        return this.totalMinutes;
    };
    
    Quota.prototype.toString = function(format){
        format = format || "hh:mm";
    
        return format.replace.call(this, /hh?|mm?/g, function(match){
            switch (match) {
                case "hh":
                    return this.totalMinutes * 60;
                case "mm":
                    return this.totalMinutes;
            }
        });
    };
    

    你能解释一下为什么下面的电话 toString() ...

    var q1 = new Quota(60);
    console.log( q1.toString() );
    

    内部误差 message=“递归太多”, 更多…}

    我正在Firebug控制台中运行代码(Firefox3.5.7+Firebug 1.5)。理想情况下,我想知道递归回调在哪里 toString() call apply

    1 回复  |  直到 15 年前
        1
  •  5
  •   Kobi    15 年前
    return format.replace.call(this, /hh?|mm?/g, function(match)
    

    format.replace 试着打电话 this.toString ,以无限递归结束。根据要求,以下是发生这种情况的证据: http://jsbin.com/eweli/ :

    var Quota = function(totalMinutes){
        this.totalMinutes = parseInt(totalMinutes || 0, 10);
    };
    
    Quota.prototype.toString = function(format){
        alert ("Quota.prototype.toString is called");
    };
    
    var q1 = new Quota(60);
    var a = "string".replace.call(q1,'hello','world');
    

    请尝试以下方法:

    return format.replace(/hh?|mm?/g, function(match)
    

    编辑

    撇开问题不谈,我发现允许函数访问当前配额的最佳方法是在其闭包之外创建一个变量:

    Quota.prototype.toString = function(format){
        format = format || "hh:mm";
        var quota = this;
        return format.replace(/hh|mm/g, function(match){
            switch (match) {
                case "hh":
                    return quota.totalMinutes / 60;
                case "mm":
                    return quota.totalMinutes;
            }
            return match;
        });
    };