2

I facing-out a problem when use Regexp for restrict to enter HTML entity into text-area.

I used this Regexp - /<(.|\n)*?>/g; for restrict HTML entity and it's work fine for me, but when i declare the global variable and used this regexp, It's give me different - different test cases(true/false) each time.

There is a Jsfiddle - Try This

when you click on "submit" button first time you get "true" and second time you get "false" for same content.

Can any one tell me why my regexp return different - different test cases each time when declare it globally?

Thank for your help...!!!

Ishan Jain
  • 8,063
  • 9
  • 48
  • 75
  • You should never use anything like `(.|\n)` in your regexes; see [this question](http://stackoverflow.com/q/2407870/20938) for the reasons why. The traditional way to match anything-including-newlines in JavaScript is `[\s\S]`, but you can usually do better than that. In this case you could use `/<[^<>]+>/`. – Alan Moore Sep 17 '13 at 07:19

2 Answers2

7

This is because you're using the g flag on the RegExp.

If you need to use g, you can define your regexp inside the function so you get a fresh one each time

function CheckContent(){
  var RegForRestrictHtmlTags2 = /<(.|\n)*?>/g;  
  $('#txtJobDesc').val("AAAAAAAA<fff>AAAAAA");
  alert(RegForRestrictHtmlTags2.test($('#txtJobDesc').val()));
}

When using the g flag, you can use .test to find multiple occurrences within your subject string. .test will continue to return true for each unique match. Once .test return false, it will effectively "reset" to the starting position.

Consider this simple example

> var re = /a/g;
undefined

> var str = 'aaaaab';
undefined

> re.test(str); // first a
true

> re.test(str); // second a
true

> re.test(str); // third a
true

> re.test(str); // fourth a
true

> re.test(str); // fifth a
true

> re.test(str); // no more a's; reset
false

> re.test(str); // back to first a
true
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • One thing worth notice is that you can call `test` (with `g` flag) on different strings, and it will just chuck on ahead from the last recorded index. – nhahtdh Sep 17 '13 at 06:34
4

The problem is that you are using g flag on the RegExp literal. The solution is to remove the g flag.


According to the documentation of RegExp.test() (emphasis mine):

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.

After the first call to test, the lastIndex property of the RegExp object /<(.|\n)*?>/g is updated. The index used as the offset for the second call to test. Since there is no more match for the pattern, the second call returns false and lastIndex is reset to 0. You can see the lastIndex property of the regex being changed in this JSFiddle.

Removing the g flag will cause the engine to ignore the lastIndex property.

I have described in detailed behaviour of RegExp.exec (which is also the same for RegExp.text) in this post.

Community
  • 1
  • 1
nhahtdh
  • 55,989
  • 15
  • 126
  • 162