20

我正在尝试使用 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 中的简单字符串!是的,一个字符串!”。

这是发生的事情:

  1. 我们得到一个字符串,其大括号中的值需要替换
  2. 循环使用“replaceArray”来查找花括号中需要替换的所有值
  3. 这些值以及花括号将被替换为“replaceWith”数组中的相应值

但是,我没有任何运气,特别是因为一个值可能会在多个位置被替换,并且我正在处理正则表达式中的动态值。

谁能帮我解决这个问题,使用与上述类似的设置?

4

5 回答 5

19

首先,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]);
}
于 2011-03-17T03:00:51.960 回答
7

我发现做到这一点的最好方法是使用其他人提到的内联替换功能,以及我从谁那里借来的。特别向@yannic-hamann 大喊正则表达式和清晰的示例。我不担心性能,因为我这样做只是为了构建路径。

我在MDN 的文档中找到了我的解决方案。

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}`)

于 2019-03-01T02:19:13.210 回答
6

字符串是不可变的

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来简化循环条件。

2017 年更新

现在你可以让它变得更简单:

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]);

演示

模板引擎

您基本上是在创建自己的模板引擎。如果您想改用现成的解决方案,请考虑使用:

或类似的东西。

您尝试使用 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);

演示

于 2011-03-17T02:59:14.440 回答
4

这是一个接受字符串和替换数组的函数。它足够灵活,可以重复使用。唯一的问题是,您需要在字符串中使用数字而不是字符串。例如,

var str = "{0} membership will start on {1} and expire on {2}.";

var arr = ["Jamie's", '11/27/14', '11/27/15'];

function personalizeString(string, replacementArray) {
  return string.replace(/{(\d+)}/g, function(match, g1) {
    return replacementArray[g1];
  });
}

console.log(
  personalizeString(str, arr)
)

演示:https ://jsfiddle.net/4cfy7qvn/

于 2014-11-27T00:33:36.230 回答
2

我真的很喜欢rsp的回答。特别是“没有循环”部分。尽管如此,我发现代码并不那么直观。我知道这个问题来自两个数组场景,并且已经超过 7 年了,但是由于在搜索用花括号替换字符串时这个问题在谷歌上显示为 #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()]);

这个资源确实帮助我构建和理解上面的代码,并总体上了解更多关于使用 JavaScript 的正则表达式。

于 2018-08-27T09:41:25.110 回答