Asked  7 Months ago    Answers:  5   Viewed   47 times

Is it possible to create a template string as a usual string

let a="b:${b}";

an then convert it into a template string

let b=10;
console.log(a.template());//b:10

without eval, new Function and other means of dynamic code generation?

 Answers

42

As your template string must get reference to the b variable dynamically (in runtime), so the answer is: NO, it's impossible to do it without dynamic code generation.

But, with eval it's pretty simple:

let tpl = eval('`'+a+'`');
Tuesday, June 1, 2021
 
SkyNet
answered 7 Months ago
13

Use constant function

echo constant("ERROR_0");
Wednesday, March 31, 2021
 
alioygur
answered 9 Months ago
67

You should never just "enter the exact contents of $_POST['...']" into any database field : it's a door opened to SQL Injections.

Instead, you must make sure the data you are injection into your SQL queries are actually valid, according to the expected DB datatypes.


For decimals, a solution, on the PHP side, would be to use the floatval function :

$clean_price = floatval($_POST['price']);
$query = "insert into your_table (price, ...) values ($clean_price, ...)"
if (mysql_query($query)) {
    // success
} else {
    echo mysql_error();   // To help, while testing
}

Note that I didn't put any quote arround the value ;-)

Saturday, May 29, 2021
 
Hat
answered 7 Months ago
Hat
92

One difference with eval is that template literals are parsed at compile time, while the argument to eval only gets parsed at run-time, when eval is executed.

Related to this, is that eval can get a dynamically built argument, while a template literal is ... literal: it cannot be stored as a template variable, which you could build dynamically, move around and eventually parse: there is no "template variable" data type. A tag function does not actually get a template variable as argument, but the parsed components of it, which are known at compile-time.

Some examples

With eval you can have this situation:

var code = prompt('enter some evil code');
eval(code);

But that is not possible with template literals:

var literal = prompt('enter some evil template literal');
tag literal; // there is no data type or syntax for this.
`${literal}`; // and this just gives you the entered string.

What is possible, is this:

var str = prompt('enter some string');
tag`${str}`;

But that does not lead to unwanted code execution, at least not worse than this:

var str = prompt('enter some string');
myfunc(str);

Any function calls must already be encoded literally in a template literal. Values of string variables cannot change that. There is no way a variable function gets called by a template literal. This:

`${func(str)}`;

...will call func, and that function only. It is chosen by the programmer.

A rather evil template literal

Having said that, this is still possible:

var func = prompt ("enter some evil function name (suggestion: 'alert')");
var param = prompt ("now provide an argument for " + func);

`${window[func](param)}`;

But it is evident that the program willingly opens up the possibility to execute any function on the global object. Then indeed, you are getting close to the evilness of eval.

Note that the same effect is achieved with:

window[name](param);

The most evil template literal

As commented, then you might as well make this template literal:

`eval(str)`;

... and so the evil part is not so much in the template literal, but the generic function call you have designed to be in it. For that you don't need template literals or eval, but a bad programmer ;-)

On the Example

You gave this example:

let ii = 1;
function counter() {
    return ii++;
}
console.log(`${counter()}, ${ii++}, ${counter()}`);

This executes your counter function, but the difference with eval is that the string literal was already there at design time, and could not have been constructed at run-time. This code is designed to increment your counter, and is not essentially different from:

console.log(counter() + ', ' + (ii++) + ', ' + counter());

Compile Time

To stress the difference of compile/run time parsing, note that you cannot run code with a template literal that does not have valid syntax.

Compare these two scripts:

alert('press OK');
eval('alert("hello)');

and:

alert('press OK');
`${alert("hello)}`;

Note the syntax error. The first script will only notice the syntax error at run-time when the argument to eval is parsed, while the second script will not even run, and give the syntax error immediately.

Put more exactly, eval executes a new script, with its own compile and run phases. A template literal is parsed/compiled like other code.

Wednesday, August 11, 2021
 
Rob13
answered 4 Months ago
43

Lets take a step back and see what is actually going on here. I think you are misunderstanding the point MDN is trying to make. The only function that is executed in your example is eval. The (...) the documentation is mentioning are not for executing the function inside the string but for changing how the function definition is evaluated.

A function call would function a(){}() but the docs talk about putting the function definition inside parenthesis: (function(){}).


There are basically thee major ways to define functions:

  1. Function declaration

    function foo() {}
    
  2. Function expression

    var foo = function() {}
    
  3. Arrow function

    var foo = () => {}
    

To understand the difference between a function declaration and a function expression, we have to understand the difference between statements and expressions (a declaration is basically like a statement).

A statement is something that has side effects and does not produce a value. if, for, switch, etc are all statements.

An expression is something that produces a value. E.g. 5 is a number literal that produces the value 5. 5 + 3 is an expression that computes the sum of the two literals, i.e. evaluating it will return the value 8.

A function declaration is like a statement. It doesn't produce a value itself, but as a side effect, a variable is defined whose value is a function (you can see in the specification that nothing happens when a function declaration is evaluated (they have already been processed at that point)).

A function expression is very similar, but instead of defining a variable, evaluating it simply results in the function object.

And that is the reason why

eval('function a() {}') // undefined, but a is defined as side effect
eval('(function a() {})') // a function object

produce different results. The first is interpreted as function declaration. A variable a will be created, but no value is created that eval could return. In the second case, the grouping operator ((...)) forces the function definition to be interpreted as a function expression, which means that a value is produced and return by eval.


Now regarding arrow functions: There is no ambiguity here. Arrow function definitions are always expressions, i.e. evaluating them always produces a value.

eval(`() => {}`) // a function object

To sum up

While there is a difference between arrow functions and function declarations/expressions, this difference is not the reason for the results you are seeing with eval. The difference here is because of evaling a statement/declaration and an expression.

Wednesday, September 1, 2021
 
Lightness Races in Orbit
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share