Ответ @chris превосходен, я просто хочу предложить альтернативное решение с использованием регулярных выражений, которое работает «наоборот», т. Е. Не ищет вхождения «версий-заполнителей» всех элементов в свойствах.map, но путем многократного поиска вхождений самого заполнителя и замены его соответствующим значением из карты свойств.У этого есть два преимущества:
- Если карта свойств становится очень большой, это решение должно иметь лучшую производительность (хотя все еще нужно сравнивать).
- Заполнитель и способ работы подстановок могутлегко изменить, отрегулировав регулярное выражение и функцию подстановки (здесь это может быть не проблема).
Недостатком, конечно, является то, что код немного сложнее (отчасти из-заДело в том, что в JavaScript отсутствует хороший способ подстановки совпадений регулярных выражений с использованием пользовательских функций, поэтому substituteRegExp
предназначен для этого:
function substituteRegExp(string, regexp, f) {
// substitute all matches of regexp in string with the value
// returned by f given a match and the corresponding group values
var found;
var lastIndex = 0;
var result = "";
while (found = regexp.exec(string)) {
var subst = f.apply(this, found);
result += string.slice(lastIndex, found.index) + subst;
lastIndex = found.index + found[0].length;
}
result += string.slice(lastIndex);
return result;
}
function templateReplace(string, values) {
// repeatedly substitute [key] placeholders in string by values[key]
var placeholder = /\[([a-zA-Z0-9]+)\]/g;
while (true) {
var newString = substituteRegExp(string, placeholder, function(match, key) {
return values[key];
});
if (newString == string)
break;
string = newString;
}
return string;
}
alert(templateReplace("hello [[b]] [my] [name]", {
"name":"world",
"my":"beautiful",
"a":"[b]",
"b":"c",
"c":"my"
})); // -> "hello my beautiful world"
Обновление : я провел небольшое профилирование для сравнениядва решения (jsFiddle на http://jsfiddle.net/n8Fyv/1/, Я также использовал Firebug).Хотя решение @chris быстрее для небольших строк (нет необходимости разбирать регулярное выражение и т. Д.), Это решение работает намного лучше для больших строк (порядка тысяч символов).Я не сравнивал различные размеры карты свойств, но ожидал еще больших различий.
Теоретически это решение имеет время выполнения O ( k n ), где k - глубина вложения заполнителей, а n - длина строки (при условии, что для поиска в словаре / хэше требуется постоянное время), в то время как решение @chris равно O (k n m ) где m - количество объектов на карте свойств.Разумеется, все это относится только к крупным входам.