Как использовать литерал 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 = {
/é/g : "é",
/è/g : "è"
// etc...
};
for (var key in keys) {
result = result.replace(key, keys[key]);
}
return result;
}
Ответы
Ответ 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(/é/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
Ответ 3
Ключи объекта не могут быть объектами RegExp. Вы должны использовать строку или действительный идентификатор. При этом вы можете сделать что-то вроде этого:
var kv = {
"/key/g": "value"
};
Мне любопытно. Почему вы хотите это сделать?
EDIT: Я частично ошибаюсь. Объекты RegExp могут использоваться как ключи, но не использовать синтаксис литерала объекта. См. Ответ jmar777.
Ответ 4
Вы также можете использовать выражение в качестве ключа, заключив его в []
при создании объекта:
var kv = {
[/key/g] : "value"
};