Нет прямого, встроенного способа (ну, ладно, возможно, есть & mdash; см. Ниже), но если вы используете функцию обратного вызова функции replace
, где замена может быть функцией, а не строкой (возвращаемое значение - это то, что подставлено), вы можете реализовать это довольно легко.
Например, предположим, что вы используете нотацию Ruby #{xyz}
для ваших заполнителей. Этот код перебирает те, которые:
var mappings, str;
str = "One #{X} three #{Y} five";
mappings = {
"X": 2,
"Y": 4
};
str = str.replace(/\#\{([^#]+)\}/g, function(match, key) {
var result;
result = mappings[key];
/* ...processing here */
return result;
});
Результирующая строка - One 2 three 4 five
, потому что #{X}
и #{Y}
были заменены поиском. Вы можете посмотреть на ключ и посмотреть, является ли оно выражением и его нужно оценивать, а не просто искать. Это оценка, где ваша настоящая работа приходит.
Теперь вы можете использовать with
и eval
для поддержки выражений; измените строку result = mapping[key];
выше на эту:
with (mappings) {
result = eval(key);
}
Если вы введете туда строку "One #{X} three #{Y} five #{X + Y * 2}"
, результат будет One 2 three 4 five 10
& mdash; потому что 2 + 4 * 2
= 10.
Это работает, потому что with
помещает данный объект поверх цепочки областей видимости, поэтому это первое, что проверяется при разрешении неквалифицированной ссылки (например, X
), а eval
выполняет код JavaScript & mdash; и поэтому может оценивать выражения & mdash; и волшебным образом делает это в объеме, в котором это называется. Но будьте осторожны; как указал Эрик, не все операторы одинаковы в различных формах выражения, и, в частности, Javascript интерпретирует ^
как «побитовый XOR», а не «в степени». (У него нет оператора экспоненты; вы должны использовать Math.pow
.)
Но вы должны быть очень осторожны с такими вещами, и with
и eval
(каждый по-своему) могут быть проблематичными. Но основные проблемы с with
заключаются в том, что трудно сказать, откуда что-то приходит и куда оно пойдет, если вы выполняете задание, а вы нет; и основные проблемы с eval
связаны с его использованием для интерпретации строк, которые вы не контролируете. Пока вы сохраняете меры безопасности и знаете о проблемах ...
Сведение в функцию:
function evaluate(str, mappings) {
return str.replace(/\#\{([^#]+)\}/g, function(match, key) {
var result;
with (mappings) {
result = eval(key);
}
return result;
});
}
alert(evaluate(
"The expression '(#{X} + #{Y}) * 2' equals '#{(X + Y) * 2}'",
{"X": 2, "Y": 4}
)); // alerts "The expression '(2 + 4) * 2' equals '12'"
alert(evaluate(
"The expression '(#{X} + #{Y}) * 2' equals '#{(X + Y) * 2}'",
{"X": 6, "Y": 3}
)); // alerts "The expression '(6 + 3) * 2' equals '18'"