Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a RegExp literal as object key?

Tags:

javascript

I would like to use create a object that contains regular expressions as the key value. I tried to use the following syntax:

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

But it fails according JavaScript lint:

SyntaxError: invalid property id 

How can I fix it?

Update

Background: The reason why I want to do this is to implement a workaround that fixes wrong unicode in a HTTP API result. I know this is very hackish, but since I have no control over the API server code I think this is the best I can do.

Currently I implemented the mapping by having a keys array and a values array:

function fixUnicode(text) {      var result = text;     var keys = [];     var values = [];     keys.push(/&Atilde;&copy;/g); values.push("&eacute;");     keys.push(/&Atilde;&uml;/g); values.push("&egrave;");     keys.push(/&Atilde;&ordf;/g); values.push("&ecirc;");     keys.push(/&Atilde;&laquo;/g); values.push("&euml;");     keys.push(/&Atilde;&nbsp;/g); values.push("&agrave;");     keys.push(/&Atilde;&curren;/g); values.push("&auml;");     keys.push(/&Atilde;&cent;/g); values.push("&acirc;");     keys.push(/&Atilde;&sup1;/g); values.push("&ugrave;");     keys.push(/&Atilde;&raquo;/g); values.push("&ucirc;");     keys.push(/&Atilde;&frac14;/g); values.push("&uuml;");     keys.push(/&Atilde;&acute;/g); values.push("&ocirc;");     keys.push(/&Atilde;&para;/g); values.push("&ouml;");     keys.push(/&Atilde;&reg;/g); values.push("&icirc;");     keys.push(/&Atilde;&macr;/g); values.push("&iuml;");     keys.push(/&Atilde;&sect;/g); values.push("&ccedil;");      for (var i = 0; i < keys.length; ++i) {         result = result.replace(keys[i], values[i]);     }     return result; } 

But I want to implement to use a JavaScript object to map keys as values:

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; } 
like image 698
StackedCrooked Avatar asked Sep 09 '11 17:09

StackedCrooked


People also ask

What is a RegExp object?

A regular expression is an object that describes a pattern of characters. The JavaScript RegExp class represents regular expressions, and both String and RegExp define methods that use regular expressions to perform powerful pattern-matching and search-and-replace functions on text.

What is the RegExp object constructor used for?

RegExp() constructor. The RegExp constructor creates a regular expression object for matching text with a pattern. For an introduction to regular expressions, read the Regular Expressions chapter in the JavaScript Guide.

What is IG in RegEx?

The g and i modifiers have these meanings: g = global, match all instances of the pattern in a string, not just one. i = case-insensitive (so, for example, /a/i will match the string "a" or "A" .

Which of the following syntax is correct for creating a RegExp object?

Syntax for creating a RegExp object: 1. var txt=new RegExp(pattern,attributes);


1 Answers

This can be done, but not using object literal syntax. You'll need to do it like this:

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


Edit: this could probably use some explaining. As xanatos commented below, what's really happening here is that the key, /key/g in this case, is being toString()'d to create the key. This is important to know, because it has an effect on key uniqueness. Consider the following:
var x = {},     reg = /foo/;  x[reg] = 'bar'; console.log(x[reg]); // "bar" console.log(x[reg.toString()]); // "bar" console.log(x['/foo/']); // "bar' 

In summary, I'm semi-scared to ask why you need to do this, but assuming you have your reasons, be careful and make sure you understand what is really happening :)


Edit 2: So in response to your updated question, you should be able to achieve something pretty close to what you want. You can use the object literal syntax as long as you wrap the regular expression in quotes. Unfortunately that means you'll have to manually reconstruct an actually RegExp object out of that key though. For example:
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 


Edit 3: Because, why not. I was so stuck on making your object-literal syntax work, that I didn't consider the fact that you never need to actually look up the replacement by the pattern itself (i.e., there's no need for object keys at all). Here's a more efficient approach using arrays that doesn't require the RegExp reconstruction:
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 


Edit 4: Because I'm bored and I like this question. Here's the ninja version:
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 
like image 66
jmar777 Avatar answered Sep 21 '22 06:09

jmar777