Подтвердить что ты не робот

Как использовать литерал RegExp как ключ объекта?

Я хотел бы использовать создать объект, который содержит регулярные выражения в качестве значения ключа. Я попытался использовать следующий синтаксис:

var kv = {
    /key/g : "value"
};

Но это не соответствует JavaScript lint:

SyntaxError: invalid property id

Как я могу это исправить?

Update

Справочная информация. Причина, по которой я хочу сделать это, - это реализовать обходной путь, который исправляет неправильный Unicode в результате HTTP API. Я знаю, что это очень хаки, но поскольку я не контролирую код 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;
}
4b9b3361

Ответ 1

Это можно сделать, но не использовать синтаксис литерала объекта. Вам нужно сделать это следующим образом:

var kv = {};
kv[/key/g] = "value";
console.log(kv[/key/g]); // "value"

<ч/" > Редактирование: возможно, это может быть объяснение. Как прокомментировал xanatos ниже, что на самом деле происходит здесь, заключается в том, что ключ /key/g в данном случае является toString() 'd для создания ключа. Это важно знать, потому что это влияет на ключевую уникальность. Рассмотрим следующее:

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

Ответ 2

Я думаю, что этот вопрос заслуживает обновленного ответа. Начиная с ES6, новый тип (стандартный встроенный объект) под названием Map был создан, чтобы покрывать подобные случаи среди прочих.

Карта очень похожа на объект, за исключением того, что позволяет использовать любой тип в качестве ключа.

Затем 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

Ответ 3

Ключи объекта не могут быть объектами RegExp. Вы должны использовать строку или действительный идентификатор. При этом вы можете сделать что-то вроде этого:

var kv = {
    "/key/g": "value"
};

Мне любопытно. Почему вы хотите это сделать?

EDIT: Я частично ошибаюсь. Объекты RegExp могут использоваться как ключи, но не использовать синтаксис литерала объекта. См. Ответ jmar777.

Ответ 4

Вы также можете использовать выражение в качестве ключа, заключив его в [] при создании объекта:

var kv = {
    [/key/g] : "value"
};