8

我想实现一个字符串格式化程序。我使用了格式化程序,它接受字符串,就像"the quick, brown {0} jumps over the lazy {1}"您传入参数的位置一样,其基数位置用于替换大括号整数。我希望能够做一些更像"the quick, brown {animal1} jumps over the lazy {animal2}"animal1 和 animal2 是变量并且被简单评估的事情。我实现了以下方法,但随后意识到 eval 不起作用,因为它不使用相同的范围。

String.prototype.format = function() {
    reg = new RegExp("{([^{}]+)}", "g");
    var m;
    var s = this;
    while ((m = reg.exec(s)) !== null) {
        s = s.replace(m[0], eval(m[1]));
    }
    return s;
};
  1. 有没有办法在不使用 eval 的情况下做到这一点(看起来不像)。
  2. 有没有办法给 eval 闭包以便获得范围?我试过 with(window)and window.eval(),但是没有用。
4

3 回答 3

6

对于像这样的用法var result = "This will get formatted with my {name} and {number}".format({name: "TetsujinOni", number: 1234});

为什么不朝这个方向前进:

String.prototype.format = function(scope) {
    reg = new RegExp("{([^{}]+)}", "g");
    var m;
    var s = this;
    while ((m = reg.exec(s)) !== null) {
        s = s.replace(m[0], scope[m[1]]);
    }
    return s;
};
于 2013-10-08T17:35:23.177 回答
5

所有全局变量都在window对象中定义,因此您应该能够在没有 eval 的情况下执行此操作:

String.prototype.format = function(scope) {
    scope = scope || window; //if no scope is defined, go with window
    reg = new RegExp("{([^{}]+)}", "g");
    var m;
    var s = this;
    while ((m = reg.exec(s)) !== null) {
        s = s.replace(m[0], scope[m[1]]);
        //                  ^^^^^^^^^^^
    }
    return s;
};

在这里,您还应该能够简单地更改window为您喜欢的范围。

如果变量不在全局范围内,而是在您当前的范围内,您可能需要阅读此内容或使用Tetsujin 的解决方案

于 2013-10-08T17:32:47.770 回答
1

哦,是的...... javascript变量插值的圣杯......你实际上可以通过使用这样的黑魔法来传递本地范围:

String.prototype.format = function(_eval) {
    return this.replace(/{(.+?)}/g, function($0, $1) {
        return _eval($1);
    })
};

function foo() {
    var a = 123, b = 456;
    s = "a is {a} and a+b={a+b}".format(function(x) {return eval(x)})
    console.log(s) // a is 123 and a+b=579
}

恐怕没有办法让format电话变得不那么冗长。

这是一个需要显式传递范围的版本,但仍然允许在{...}'s 中使用任意表达式:

String.prototype.format2 = function(scope) {
    eval(Object.keys(scope).map(
        function(x) { return "var " + x + "=scope." + x
    }).join(";"));
    return this.replace(/{(.+?)}/g, function($0, $1) {
        return eval($1);
    })
};

function foo() {
    var a = 123, b = 456;
    s = "a is {a} and a+b={a+b}".format2({a:a, b:b})
    console.log(s) // a is 123 and a+b=579
}

你不应该理解这一点。

于 2013-10-08T18:06:37.633 回答