Reputation: 6361
I just discovered the weirdest bug in some javascript code dealing with RegExp.test
. I had a regular expression regexp
declared inside a function and I had a closure that had a reference to regexp
and I was using the closure to iterate over an array of strings to test them with the help of collect
from prototype.js, i.e.
function some_func() {
var regexp = /regular_expression/;
an_array_of_strings.collect(
function(str) {
if (regexp.test(str)) {
do_something();
}
}
);
}
The really weird thing was that calling regexp.test(str)
inside the closure would alternate between true
and false
on the same input. I looked at the source for RegExp.test
and I didn't see anything fishy but there was something going on because how can the same string pass and fail the same regular expression. After staring some more at RegExp.test
I basically concluded that variables declared in RegExp.test
were continuing to exist between invocations and were messing up subsequent invocations. So here's the question: What is the difference between
this.a = 2;
and
var a = 2;
when the above statements appear inside a method being called on an object inside a closure that holds a reference to that object? I'm asking because the bug disappears when I move regexp.test
outside the closure. When regexp.test
is called outside the closure then it doesn't flip-flop between true
and false
on each call. I have no idea why this is happening.
Edit: When I was moving the regexp
outside the closure I was forgetting to add the global option so that's why the bug was disappearing. Thanks Ivo.
Upvotes: 2
Views: 943
Reputation: 46735
Since you didn't show your RegExp but I just answered something similar to this, I suppose that you're using the global
option in your RegExp, which has some interesting side effects.
As with exec (or in combination with it), test called multiple times on the same global regular expression instance will advance past the previous match.
Source: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp/test
So what exactly happens here is that since you're using the global option for the regex, it will continue to search the string after it found an match.
regexp.test("d")
This will find d at position 0.
regexp.test("d")
This will now search for d starting at position 1, but since that's the end of the string it will not find anything therefore returning false.
We can use the lastIndex
property of the regex to proof that:
regexp.lastIndex
>> 0
regexp.test("d")
>> true
regexp.lastIndex
>> 1
regexp.test("d")
>> false
So to solve the issue you need to remove the global
option from your RegExp.
Disclaimer, this is a copy of my previous answer:
Unusual javascript Regex result, explanation please!
Upvotes: 3
Reputation: 720
Have a look at this page about the wonders of this
in JS. The meaning of this
changes quite dramatically, depending on how you use your functions.
Upvotes: 1
Reputation: 86
This is a tricky question, as at first glance they appear to be identical.
I would surmise that this.a
is owned by the function, but may also extend for the life of that function, not just the function call itself; whereas var a
would be created and destroyed each time the function is executed.
Upvotes: 1