How to implement a string formatter with variable names

I would like to use a string formatter. I used formatters that take a string like "the quick, brown {0} jumps over the lazy {1}" , where you pass parameters whose cardinal location is used to replace integers. I would like to do something more than "the quick, brown {animal1} jumps over the lazy {animal2}" , where animal1 and animal2 are variables and are simply evaluated. I got the following method, but then I realized that eval will not work because it does not use the same scope.

 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; }; 
  • Is there a way to do this without using eval (not like this).
  • Is there a way to give eval a closure to make it work? I tried with(window) and window.eval() , but that did not work.
+7
javascript formatting string-formatting
source share
3 answers

For use, for example var result = "This will get formatted with my {name} and {number}".format({name: "TetsujinOni", number: 1234});

Why not go down in this direction:

 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; }; 
+4
source share

All global variables are defined in the window object, so you can do this without 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; }; 

Here you can also just change the window to the area that you like.

If the variables are not in the global scope, but rather in your current scope, you could read this or go with the Tetsujin solution .

+5
source share

Oh yes ... the holy grail of interpolating javascript variables ... In fact, you can pass the local area around using dark magic as follows:

 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 } 

I'm afraid there is no way to make the format call less verbose.

And here is the version that requires explicit transfer of visibility, but still allows arbitrary expressions in {...} '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 } 

You should not understand this.

+1
source share

All Articles