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)とを試し window.eval()ましたが、うまくいきませんでした。
4

3 に答える 3

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 に答える