0

I get false checking "AA8187517" string by the regex:

if (/^[a-z0-9]*$/i.test(value))

What I suddenly see in the console?

> value.split('').filter(function(el){ return el != '' })
<  (11) ["", "A", "A", "8", "1", "8", "7", "5", "", "1", "7"]

console

What are these two values in the array?

melpomene
  • 84,125
  • 8
  • 85
  • 148
Igor
  • 281
  • 4
  • 12

3 Answers3

3

The two "empty" values in your array contain character 8207 (decimal), which is 200f (hex).

U+200F is RIGHT-TO-LEFT MARK in Unicode, an (invisible) marker that changes the direction text is displayed.

Here's a reproduction of your issue plus sample code to remove the character:

let value = "\u200FAA81875\u200F17";

console.log(value.split('').map(function (x) { return x.charCodeAt(0); }));

value = value.replace(/\u200F/g, '');

console.log(/^[a-z0-9]*$/i.test(value));
melpomene
  • 84,125
  • 8
  • 85
  • 148
  • Actually the problem was that I had the Unicode characters which were removed by value.replace(/[^\x00-\x7F]/g, "") – Igor Apr 21 '19 at 15:56
  • If the goal is filtering, then suggesting replacing as a solution is a half truth. One should be able to filter out unwanted values. – Anthony Rutledge Apr 21 '19 at 18:10
1

Four thoughts.

1) I would use explicit regular expressions, where practical, instead of modifiers. Be wary of the * quantifier, as it may allow too much, including the absence of a value!!!

if (/^[A-Za-z0-9]*$/.test(value)) {

}

2) Examine closely the definition of Array.protoype.split(), and what happens when you use the empty string as the separator.

Attention: If an empty string ("") is used as the separator, the string is not split between each user-perceived character (grapheme cluster) or between each unicode character (codepoint) but between each UTF-16 codeunit. This destroys surrogate pairs. See also How do you get a string to a character array in JavaScript? on stackoverflow.

3) Could .trim() be of any use to you here?

value.trim().split('').filter(function(el){ return el != '' })

4) Consider changing your filter predicate (the callback method).

value.trim().split('').filter(function(element){ return /^[A-Za-z0-9]{1}$/.test(element) }

However, investigate the significance of splitting on the empty string and know the encoding of your source strings. Since you are filtering, you should not need to replace before filtering. Filtering alone should be sufficient. You want to whitelist wanted values, as blacklisting by replacing is bound to get you in trouble here.

Stackoverflow: How do you get a string to a character array in JavaScript?

Anthony Rutledge
  • 6,980
  • 2
  • 39
  • 44
-2

No you just should save the result in a new variable:

let array = ["text", "text2", '', 'text3'];

let a = array.filter((currentValue) => currentValue);
console.log(a); //["text", "text2", 'text3']
Mark Minerov
  • 309
  • 1
  • 8