Today I learned about javascript lookahead, lookbehind , and both negative lookahead and lookbehind assertions. The freecodecamp curriculum briefly touched on it but not enough for me to fully grasp the idea of it. It took me about 8 hours ( split between two days ) to understand how to use’em.
I’ll get to what they are in a minute, but first I’d like to stay that the way they’re described is a bit confusing. The lookahead / lookbehind way of teaching just didn’t sit well with me. For me to grasp the concept behind them, I needed to think of them as little if statements ( or mini ternary operators ).
Keep that in mind for now; as you’ll see what I’m talking about.
Javascript assertions ( lookahead, lookbehind, etc) were added to ES6, and provide you with additional superpowers. They give you the ability to match given criteria if and only if set character(s) is present before or after the criteria that you’re trying to match, hope you understood that because that’s the probably the best that I can do at this time. If I come up with a better way of breaking it down, I’ll update this post.
Before I give you some examples, here are the assertions that you will need to be familiar with:
x(?=y)
Lookahead assertion: This assertion only matches ‘x’ if and only if ‘y’ is followed by ‘x’.
x(?!y)
Negative lookahead assertion: This only matches if ‘x’ is NOT followed by ‘y’.
(?<=y)x
Lookbehind assertion: This assertion only matches ‘x’ if and only if ‘y’ is directly before ‘x’’.
(?<=y)x
Negative Lookbehind assertion: This assertion only matches ‘x’ if and only if ‘y’ is not directly before ‘x’.
If you would like to learn more about them, check out MDN here: Mozilla’s Javascript MDN
Lets start with some lookbehind assertion examples.
(?<=y)x
let phoneNumbers = `
(718)535-6873
(413)535-6873
(803)535-7848
(718)535-9873
(212)555-6854
(718)457-6113`;
let myRegex = /(?<=\(718\))\d{3}-\d{4}/g
//output [ '535-6873', '535-9873', '457-6113' ]
In the example, above, \d{3}-\d{4} is our ‘x‘ and (? <=\718\)) is our ‘y’. It matches because the seven digits immediately follow the parentheses, not the number 8. So if this regular expression could speak, what would it actually say?
“I will provide you with 7 digits for a phone number if and only if there is an area code of 718 surrounded by parenthesis preceding the 7 digits.”
What happens when I remove the right parentheses?
let myRegex2 = /(?<=\(718)\d{3}-\d{4}/ //output null
/
I removed
the right parentheses.
Meaning, it is essentially looking for:
(718535-6873
We’re gifted a result of null.Why? Because based on the string, a parentheses comes before the ‘535’, not an‘8’.
Here is another example using a lookbehind assertion.
let myFruits= `oranges banana pears banana peach banana`;
let myRegex3 = /(?<=pears )banana/
//output [ 'banana', index: 21, input: 'oranges banana pears banana peach banana',
groups: undefined ]
So what is this one saying?
“I will provide you with the word ‘banana‘, if an only and only if the word ‘pears‘ followed by a space is preceding the word ‘banana’ “
NOTE: Within the lookbehind, notice the space between the word pears and the closing parentheses.
let myRegex3 = /(?<=pears )banana/
/
This is your white space.
or you can use /(?<=pears\s)banana/
Lookahead example
//* Providing website names with a TLD of.com
let myHtmlCode = `
href=\'www.SITE1.com\'>yourSite
href=\'www.SITE2.org\'>yourSite
href=\'www.SITE3.net\'>yourSite
href=\'www.SITE4.com\'>yourSite
href=\'www.SITE5.io\'>yourSite
`;
let myRegex4 = /\w+\d(?=\.com)/g
//output [ 'SITE1', 'SITE4' ]
Negative lookahead example
//change the id's to classes for both green and red buttons while excluding the orange id
let myHtml = `
class='blueBtn'
id='greenBtn'
id='redBtn'
id='orange'
`;
let myRegex5 = /id(?!\W+orange)/g
let changeToClass = myHtml.replace(myRegex5, 'class')
//output, below
class='blueBtn'
class='greenBtn'// <--- changed from id to class
class='redBtn' // <--- changed from id to class
id='orange' //<--- Untouched!
I think this is a pretty cool tool to have in your utility belt. If you found this post useful, let me know in the comments below.