我想使用创建一个包含正则表达式作为键值的对象。我尝试使用以下语法:
var kv = {
/key/g : "value"
};
但它根据JavaScript lint失败了:
SyntaxError: invalid property id
我该如何解决?
背景:我之所以这样做,是为了实现修复HTTP API结果中错误的unicode的解决方法。我知道这非常hackish,但由于我无法控制API服务器代码,我认为这是我能做的最好的。
目前,我通过使用键数组和值数组来实现映射:
function fixUnicode(text) {
var result = text;
var keys = [];
var values = [];
keys.push(/é/g); values.push("é");
keys.push(/è/g); values.push("è");
keys.push(/ê/g); values.push("ê");
keys.push(/ë/g); values.push("ë");
keys.push(/Ã /g); values.push("à");
keys.push(/ä/g); values.push("ä");
keys.push(/â/g); values.push("â");
keys.push(/ù/g); values.push("ù");
keys.push(/û/g); values.push("û");
keys.push(/ü/g); values.push("ü");
keys.push(/ô/g); values.push("ô");
keys.push(/ö/g); values.push("ö");
keys.push(/î/g); values.push("î");
keys.push(/ï/g); values.push("ï");
keys.push(/ç/g); values.push("ç");
for (var i = 0; i < keys.length; ++i) {
result = result.replace(keys[i], values[i]);
}
return result;
}
但我想实现使用JavaScript对象将键映射为值:
function fixUnicode(text) {
var result = text;
var keys = {
/é/g : "é",
/è/g : "è"
// etc...
};
for (var key in keys) {
result = result.replace(key, keys[key]);
}
return result;
}
答案 0 :(得分:44)
这可以完成,但不能使用对象文字语法。你需要这样做:
var kv = {};
kv[/key/g] = "value";
console.log(kv[/key/g]); // "value"
<小时/> 编辑:这可能会使用一些解释。正如xanatos在下面评论的那样,这里真正发生的是,在这种情况下,密钥
/key/g
正在toString()
来创建密钥。这一点很重要,因为它会对密钥的唯一性产生影响。请考虑以下事项:
var x = {},
reg = /foo/;
x[reg] = 'bar';
console.log(x[reg]); // "bar"
console.log(x[reg.toString()]); // "bar"
console.log(x['/foo/']); // "bar'
总而言之,我半害怕要求为什么你需要这样做,但假设你有理由,要小心并确保你明白 真的发生了:))
<小时/> 编辑2:因此,为了回应您的更新问题,您应该能够实现与您想要的非常接近的东西。只要将正则表达式用引号括起来,就可以使用对象文字语法。不幸的是,这意味着你必须手动重建一个实际的RegExp对象。例如:
var result = "abcdef",
replacements = {
"/a/g": "FOO",
"/d/i": "BAR"
};
for (var key in replacements) {
var parts = key.split('/');
result = result.replace(new RegExp(parts[1], parts[2]), replacements[key]);
}
console.log(result); //FOObcBARef
<小时/> 编辑3:因为,为什么不呢。我一直坚持让你的对象文字语法工作,我没有考虑到你不需要实际查找模式本身的替换(即,根本不需要对象键)。这是一种使用不需要RegExp重建的数组的更有效的方法:
var result = "abcdef",
replacements = [
[/a/g, "FOO"],
[/d/i, "BAR"]
];
for (var i = 0, len = replacements.length; i < len; i++) {
var replacement = replacements[i];
result = result.replace(replacement[0], replacement[1]);
}
console.log(result); //FOObcBARef
<小时/> 编辑4:因为我很无聊,我喜欢这个问题。这是忍者版:
var result = "abcdef",
replacements = [
[/a/g, "FOO"],
[/d/i, "BAR"]
], r;
while ((r = replacements.shift()) && (result = String.prototype.replace.apply(result, r))) {}
console.log(result); //FOObcBARef
答案 1 :(得分:6)
我认为这个问题值得更新答案。从ES6开始,创建了一个名为Map的新类型(标准内置对象)来覆盖像这样的案例。
Map非常类似于Object,除了它允许任何类型作为键。
然后可以使用Map.prototype.forEach()循环遍历每个键/值对。
在您的情况下,您的功能现在可以是:
function fixUnicode(text) {
var result = text;
var replaceMap = new Map();
replaceMap.set(/é/g, "é");
replaceMap.set(/è/g, "è");
replaceMap.set(/ê/g, "ê");
replaceMap.set(/ë/g, "ë");
replaceMap.set(/Ã /g, "à");
replaceMap.set(/ä/g, "ä");
replaceMap.set(/â/g, "â");
replaceMap.set(/ù/g, "ù");
replaceMap.set(/û/g, "û");
replaceMap.set(/ü/g, "ü");
replaceMap.set(/ô/g, "ô");
replaceMap.set(/ö/g, "ö");
replaceMap.set(/î/g, "î");
replaceMap.set(/ï/g, "ï");
replaceMap.set(/ç/g, "ç");
replaceMap.forEach(function (newString, old) {
result = result.replace(old, newString);
});
return result;
}
您可以在MDN
了解有关地图的更多信息答案 2 :(得分:3)
对象键不能是RegExp对象。您必须使用字符串或有效ID。话虽这么说,你可以这样做:
var kv = {
"/key/g": "value"
};
我很好奇。你为什么要这样做?
编辑:我有些错误。 RegExp对象可用作键,但不能使用对象文字语法。请参阅jmar777的回答。
答案 3 :(得分:0)
创建对象时,也可以通过将表达式包装在[]
中来将其用作键:
var kv = {
[/key/g] : "value"
};