0

There is a bit of a long story to get to the point, but if you bear with me, I promise I'll get there. You could also skip down to the bottom and the questionable code is there.

Here's a quick rundown of what I've been doing. I'm trying to compare the value of two fields which are linked together (i.e. you put a value in one, the other should have the exact same value). The field is sort of poorly constructed. It's a drop down that has over 4000 values. Those 4000 values are not all stored in the memory I can access with my scripts but rather only the 20 or so visible in the GUI. It's not until you scroll down that the other items become visible. The drop down can be typed into so I can just treat it as a text box for testing purposes and since each item in the drop down begins with an integer, I can just type a random integer value into the drop down (I can't actually type anything but integers into the field). However, to actually test that the correct value appears in the twin field, I need to be able to account for the rest of the text which will appear. Here's an example:

I might get a random number so that

input = "300";

which will type "300" into the field. That will cause both fields to have a text value of: "300 - TEXTGOESHERE". So I thought I'd use a regular expression to simply check for whatever number I've put in + any other text that follows. So I have a function called getRandomInt(min, max) which gets a random number between the min and max values given so here's my code:

var input = getRandomInt(0,4095);
var regex = new RegExp("^" + input);

If the value if input is "300", then the value of regex will be "/^300/i". It's worth noting that the tool I'm using has a weird version of JavaScript and not exactly ES6 so I don't actually have let for example and for some reason RegExp() always adds the /i at the end instead of just /.

I was using this in my test and for some reason it wouldn't work. There was also seemingly no reason why it shouldn't work because everything showed up correctly. The only clue I got is when I thought to test an explicit regular expression and found that that worked... (I plugged in /^300/i). At this point, I'm very confused, so I decide to run a quick test.

var regex1 = /^300/i;
var regex2 = new RegExp("^300");

console.log(regex1);
console.log(regex2);
console.log(regex1 == regex2);

CONSOLE:

/^300/i
/^300/i
false

Okay... maybe it's something unique to my IDE. So I open up Chrome's console and run roughly the same test:

let regex1 = /^300/;
let regex2 = new RegExp("^300");

console.log(regex1);
console.log(regex2);
console.log(regex1 == regex2);

CONSOLE:

/^300/
/^300/
false

So I'm at a complete loss and googling hasn't returned much help. Can anyone offer any insights into why RegExp() and an explicitly declared regular expression don't appear to be equivalent?

JohnN
  • 968
  • 4
  • 13
  • 35
  • 1
    If it's a "weird version of JavaScript" then it's not JavaScript. What tool are you talking about here? – Pointy Mar 11 '20 at 16:59
  • 2
    The variables contain a reference to the different RegExp objects. – Teemu Mar 11 '20 at 16:59
  • 2
    Also two different objects, no matter how similar they appear, are **never** equal to each other. – Pointy Mar 11 '20 at 16:59
  • I've done a little more experimenting with JavaScript and it looks like regex will not show as equal to each other. `/300/ == /300/` returns as `false`. So I'm sent back to the drawing board. – JohnN Mar 11 '20 at 17:01
  • 3
    It's not just RegExp instances, it's **any** kind of object. Object equality comparisons are based on the actual identity of each object. An object is only equal to itself. – Pointy Mar 11 '20 at 17:02
  • @Pointy It has parts of ES6 but not all of it. I believe it's based in the prior version. Its a tool called Squish developed by Froglogic. – JohnN Mar 11 '20 at 17:02
  • Two separately created objects with the exact same properties are still *two separate, distinct objects*. For that reason, even this prints false: `console.log(/^300/ == /^300/);` – Peter B Mar 11 '20 at 17:02
  • You should compare `source` or `flags` as in `console.log(regex1.source == regex2.source)` or `console.log(regex1.flags == regex2.flags)` – anubhava Mar 11 '20 at 17:03
  • @anubhava What are .flags and .source returning? – JohnN Mar 11 '20 at 17:07
  • Even knowing why `// == RegExp()` wouldn't return true, I'm still baffled as to why `input = 300 - SOMETEXT;` and `regex = /^300/i` wouldn't be equivalent. – JohnN Mar 11 '20 at 17:12
  • 1
    For the reference problem, see [this answer](https://stackoverflow.com/a/38533677/1169519), and please follow the evaluation strategies link at the end of the answer. – Teemu Mar 11 '20 at 17:20

1 Answers1

1

I believe correct way to compare 2 regex would be to compare .source and .flags properties:

let regex1 = /^300/i;
let regex2 = new RegExp("^300", 'i');

console.log(regex1.source, regex1.flags);
console.log(regex2.source, regex2.flags);
console.log(regex1.source == regex2.source && regex1.flags == regex2.flags);

The source property returns a String containing the source text of the regexp object, and it doesn't contain the two forward slashes on both sides and any flags.

The flags property returns a string consisting of the flags of the current regular expression object.

As others have already pointed out that 2 different regexp objects represent 2 different reference and they will never be equal even if underlying regex are identical.

When you do regex1 == regex2, you're just comparing their references not their contents.

Community
  • 1
  • 1
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    Just an aside, `/^300/i.toString()===new RegExp("^300", 'i').toString();` appears to have the same effect. – Gary Mar 11 '20 at 17:35