Syntax for multiple positive lookaheads in JavaScript regex

Lookaheads are like wanders! You limited the domain of looks at the first place which won't fulfill the requirement. You may use a greedy dot .* (or lazy .*?) regex to allow a lookahead to look for each requirement.

As @AlexR mentioned in comments I modify the RegEx a little bit:

^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9_]{0,20}$

By the way, you forgot matching underscores, which I added.

The above is almost equal to:

^(?=[^a-zA-Z]*[a-zA-Z])(?=\D*\d)\w{1,20}$

A problem with @revos answer occurs when the input is too long: 01234567890123456789A passes both lookaheads and the final check. A fixed version either checks for end-of-string with ^ and $ or uses variable-length lookaround (or both):

^(?=.{0,19}[a-zA-Z])(?=.{0,19}[0-9])[a-zA-Z0-9]{0,20}$ // (1), (1*) without ^
^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]{0,20}$
(?=.{0,19}[a-zA-Z])(?=.{0,19}[0-9])[a-zA-Z0-9]{0,20} // (2)

Only the latter will allow text around the specified string. Omitting the ^ in the former variants will allow the password to be prefixed, i.e.

Input            : "Password1 = ASDF0123"
Matches with (1) : none
Matches with (1*): "ASDF0123"
Matches with (2) : "Password1", "ASDF0123"