You could do it in three separate matches, one for each category. That's probably the simplest method.
Otherwise you've got to take into account the six alternatives for ordering those, and of course you'd also need to sprinkle in .* all over the place to take into account the characters in between.
I guess you could also do it with three forward assertions using (?=) (only match the start of the string if there is a letter somewhere after, if there is a digit somewhere after it, and if there is a special character somewhere after it); that would be simpler than the second suggestion above, but I suspect it wouldn't be a useful amount faster than the first.
One last thing; you've gone a bit overboard with your escaping: - and $ are the only characters that need it.
Okay; tried all three and the first is easily the slowest. The fastest is the third.
/^(?=.*[a-z])(?=.*\d)(?=.*[@!#&_])/i