我正在尝试使用JavaScript动态替换花括号内的内容。以下是我的代码示例:
var myString = "This is {name}'s {adjective} {type} in JavaScript! Yes, a {type}!";
var replaceArray = ['name', 'adjective', 'type'];
var replaceWith = ['John', 'simple', 'string'];
for(var i = 0; i <= replaceArray.length - 1; i ++) {
myString.replace(/\{replaceArray[i]\}/gi, replaceWith[i]);
}
alert(myString);
上面的代码应输出“这是John在JavaScript中的简单字符串!是的,是一个字符串!”。
以下是发生的事情:
但是,我没有运气,特别是因为可以在多个位置替换一个值,并且我在正则表达式中处理动态值。
任何人都可以帮我解决这个问题,使用与上面相似的设置吗?
答案 0 :(得分:15)
首先,String.replace
不具有破坏性 - 它不会更改字符串本身,因此您必须设置myString = myString.replace(...)
。其次,您可以使用RegExp
动态创建new RegExp
个对象,因此所有结果都是:
var myString = "This is {name}'s {adjective} {type} in JavaScript! Yes, a {type}!",
replaceArray = ['name', 'adjective', 'type'],
replaceWith = ['John', 'simple', 'string'];
for(var i = 0; i < replaceArray.length; i++) {
myString = myString.replace(new RegExp('{' + replaceArray[i] + '}', 'gi'), replaceWith[i]);
}
答案 1 :(得分:5)
JavaScript中的字符串是不可变的。这意味着这将永远不会像您期望的那样工作:
myString.replace(x, y);
alert(myString);
这不仅仅是.replace()
的问题 - 在JavaScript中没有任何内容可以改变字符串。你可以做的是:
myString = myString.replace(x, y);
alert(myString);
JavaScript中的正则表达式文字不会插值,因此这仍然不起作用:
myString = myString.replace(/\{replaceArray[i]\}/gi, replaceWith[i]);
你必须做这样的事情:
myString = myString.replace(new RegExp('\{'+replaceArray[i]+'\}', 'gi'), replaceWith[i]);
但这有点乱,所以你可以先创建一个正则表列表:
var regexes = replaceArray.map(function (string) {
return new RegExp('\{' + string + '\}', 'gi');
});
for(var i = 0; i < replaceArray.length; i ++) {
myString = myString.replace(regexes[i], replaceWith[i]);
}
如您所见,您还可以使用i < replaceArray.length
代替i <= replaceArray.length - 1
来简化循环条件。
现在你可以让它变得更简单:
var regexes = replaceArray.map(string => new RegExp(`\{${string}\}`, 'gi'));
for(var i = 0; i < replaceArray.length; i ++) {
myString = myString.replace(regexes[i], replaceWith[i]);
}
不是一遍又一遍地循环和应用.replace()
函数,而是只能这样做一次:
var mapping = {};
replaceArray.forEach((e,i) => mapping[`{${e}}`] = replaceWith[i]);
myString = myString.replace(/\{\w+\}/ig, n => mapping[n]);
请参阅DEMO。
您基本上是在创建自己的模板引擎。如果您想使用现成的解决方案,请考虑使用:
或类似的东西。
使用Mustache尝试做的一个例子是:
var myString = "This is {{name}}'s {{adjective}} {{type}} in JavaScript! Yes, a {{type}}!";
var myData = {name: 'John', adjective: 'simple', type: 'string'};
myString = Mustache.to_html(myString, myData);
alert(myString);
请参阅DEMO。
答案 2 :(得分:4)
这是一个接受字符串和替换数组的函数。它足够灵活,可以重复使用。唯一的问题是,您需要在字符串中使用数字而不是字符串。例如,
var myString = "This is {0}'s {1} {2} in JavaScript! Yes, a {2}!";
function personalizeString(string, replacementArray) {
return string.replace(/({\d})/g, function(j) {
return replacementArray[j.replace(/{/, '').replace(/}/, '')];
});
}
答案 3 :(得分:1)
我发现做到这一点的最佳方法是使用内嵌的替换函数,就像其他人提到的那样,我是从中借用的。特别向@ yannic-hamann大喊正则表达式和清晰的示例。我并不担心性能,因为我只是这样做来构造路径。
我在MDN's docs中找到了解决方案。
const interpolateUrl = (string, values) => string.replace(/{(.*?)}/g, (match, offset) => values[offset]);
const path = 'theresalways/{what}/inthe/{fruit}-stand/{who}';
const paths = {
what: 'money',
fruit: 'banana',
who: 'michael',
};
const expected = 'theresalways/money/inthe/banana-stand/michael';
const url = interpolateUrl(path, paths);
console.log(`Is Equal: ${expected === url}`);
console.log(`URL: ${url}`)
答案 4 :(得分:0)
我真的很喜欢rsp的答案。尤其是“ 无循环 ”部分。尽管如此,我发现代码并不是那么直观。我知道这个问题来自两个数组的场景,已有7年之久了,但是由于这个问题在搜索用花括号替换字符串时出现在Google上的#1位置,并且作者要求使用类似的设置我很想提供另一种解决方案。
话虽如此,复制和粘贴解决方案可用于:
var myString = "This is {name}'s {adjective} {TYPE} in JavaScript! Yes, a { type }!";
var regex = /{(.*?)}/g;
myString.replace(regex, (m, c) => ({
"name": "John",
"adjective": "simple",
"type": "string"
})[c.trim().toLowerCase()]);
这个resource确实帮助我构建和理解了上面的代码,并从总体上了解了有关regex的更多信息。