如何使用RegExp文字作为对象键?

时间:2011-09-09 17:01:22

标签: javascript

我想使用创建一个包含正则表达式作为键值的对象。我尝试使用以下语法:

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 = {
        /&Atilde;&copy;/g : "&eacute;",
        /&Atilde;&uml;/g :  "&egrave;"
        // etc...
    };

    for (var key in keys) {
        result = result.replace(key, keys[key]);
    }
    return result;
}

4 个答案:

答案 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(/&Atilde;&copy;/g, "&eacute;");
    replaceMap.set(/&Atilde;&uml;/g, "&egrave;");
    replaceMap.set(/&Atilde;&ordf;/g, "&ecirc;");
    replaceMap.set(/&Atilde;&laquo;/g, "&euml;");
    replaceMap.set(/&Atilde;&nbsp;/g, "&agrave;");
    replaceMap.set(/&Atilde;&curren;/g, "&auml;");
    replaceMap.set(/&Atilde;&cent;/g, "&acirc;");
    replaceMap.set(/&Atilde;&sup1;/g, "&ugrave;");
    replaceMap.set(/&Atilde;&raquo;/g, "&ucirc;");
    replaceMap.set(/&Atilde;&frac14;/g, "&uuml;");
    replaceMap.set(/&Atilde;&acute;/g, "&ocirc;");
    replaceMap.set(/&Atilde;&para;/g, "&ouml;");
    replaceMap.set(/&Atilde;&reg;/g, "&icirc;");
    replaceMap.set(/&Atilde;&macr;/g, "&iuml;");
    replaceMap.set(/&Atilde;&sect;/g, "&ccedil;");

    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"
};