Regex.exec() returns null

<!DOCTYPE html>
<html>
<head>
  <title>Alive Time</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
  <link rel="stylesheet" type="text/css" href="style.css">
  <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
  <script src="code.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js"></script>
</head>
  <body>
    <div class="container-fluid text-center" id="head">
      <h1>Whats my alive time</h1>	
    </div>
    <div class="container text-center" id="enter">
      <div class="row" style="display: flex; justify-content: center;"> 
        <h3 style="display: inline-block; margin-right: 0.5em; ">Enter your birth date:</h3>
        <input type="text" class="form-control col-3" placeholder="mm/dd/yyyy"></input>
        <button type="submit" class="btn btn-primary col-1">GO</button>
      </div>
    </div>

   <!-- <p id="invalid" class="hid"></p>-->

  </body>

</html>
-------------------------------------------------------------------------------------------------------------------------------------
CSS:
#head{
	margin: 10em 0;

}


button{
	margin-left: 1em;
}

.hid{
	display: none;
}
----------------------------------------------------------------------------------------------------------------
$(document).ready(function(){

     $("input").focus(function(){ //whenever user focus at input placeholder value should be mm/dd/yyyy
		$("input").attr("placeholder","mm/dd/yyyy");
    });

	
   $("button").on("click",function(){ //on click function on button GO
        
    var $inp=$("input").val();//getting the value of input field
    var regex= /(\d{1,2})\/(\d{1,2})\/(\d{4})/gi;//regular expression for date format 
    if(regex.test($inp)===false){ //if format is not followed input is invalid
             $("input").attr("placeholder","Please write valid input").val("");
        }
      var arr=regex.exec($inp);//making array of input field value.['12/13/1995','12','13','1995']
      var numarr=[];
      for(var i=1;i<arr.length;i++){//loop to convert string into numbers
          var n=Number(arr[i]);//converting into numbers
          if(i===1&&n>12||i===2&&n>31){//if month or day value is invalid e.g day is 32 or month is 13
          	$("input").attr("placeholder","Please write valid input").val("");
          }
          else{
          	numarr.push(n);//if valid push that number into numarr. 
          }

          
      }

  });



})

Guys I am trying to make a small and simple web app to calculate person’s age. If I compile my program it gives an error of “cant read length property of null”.I dont know why it is having arr as null. I tried to check my arr and run it in chrome developers tool and it is giving desired results. For example if we include 12/13/1995 in input arr should be of length 4. But it is giving null error if I check console of developer tools… I couldnt figure out the problem please can anyone help me here.

  1. Try to clean up your code a little it’s pretty sloppy and hard to follow

  2. Why are you using so many different arrays? It looks like some of your code is redundant.

I have commented out my code. My program is far from complete right now the problem is not what I should I do or not. The problem is it is giving an error which doesnt make sense.

By process of elimination, the problem is with your regular expression. Input checks out but regex.exec($inp) returns null.

1 Like

I dont understand. Please can you explain it a little bit. Ite my first time I have been into this kind of error. It works fine if I try to run the same commands in chrome developer tools

Wait, I spoke too soon. It might be a problem with input too. But basically, this line

var arr=regex.exec($inp)

will return null if there’s no match. So either the regex is wrong, $input is wrong, or both. Either way, if there’s no match, you’re essentially assigning null to arr, which is why you get the cannot read property of null error – because arr.length is the same as null.length. I’m not sure why it would be different in developer tools, though.

I dont think so think so this is the problem up here. If you go to dev tools and type these specific commands
var $inp=$(“input”).val();
var regex= /(\d{1,2})/(\d{1,2})/(\d{4})/gi;
var arr=regex.exec($inp);
arr
after this you will see arr is array of 4 elements. similarly for loop and arr.length is also working. I confirmed my regex in regex101.com too. Its fine. There is some kind od another problem

It seems to work if you remove the g at the end

It looks like the g flag is the culprit, as @jx2bandito pointed out. From what I can make out of it, the earlier .test() call advances some internal pointer in the regex, so when .exec() is called, it starts looking for matches from this updated pointer, not the beginning of the string, and fails to find a match. If the g flag is removed, it will always try to start matching from the beginning. Please correct me if what I said is off.

2 Likes

Yeah, it looks like that’s it. That internal pointer appears to be the getter/setter property lastIndex.

Well thanks guys for the help. But I couldnt understand exactly why it does that so. Can you please just little elaborate the reason so I can save my code from that kinda problem in future…

Since you’re trying to match the whole string (and you don’t have the intention to search for multiple matches in a given string), you can make do without putting the g flag in your regex.

Putting the g flag gives the regex a lastIndex property, which tracks where to start looking for a match in a given string. Calling .exec() or .test() changes this property and affects further calls to either method.

I also changed the title of this thread to a more appropriate title.

1 Like