The ^ at the beginning of your regex is specifically starting the search at the beginning of the string. In other words, your expression is looking for multiple matches, but only where each match starts at index 0. Of course, the ending spaces that you’re also trying to capture start at index 16, not at index 0.
The regex /^(\s+)|\1$/g has potentially another problem, and that’s the use of the \1 backref. What this says is match any amount of regex at the beginning of the string, or the same amount of whitespace at the end. Since the only way the second alternation is going to fire is if the first one doesn’t match, the group is never defined, so it would match on zero whitespace, i.e. anything.
The short of it is, having a backref go across alternations doesn’t usually make a lot of sense, since it’s referencing a group that may not have matched anything. In fact, testing it in node, I couldn’t even make it match consistently on the same string.
I don’t fully understand it yet. Maybe I misunderstand some concept.
I am still wondering why /^\s+|\s+$/g can pass the task.
Aren’t they the same as /^(\s+)|\1$/g?
You may think so, but the \1 match exactly what was matched by the thing in round parenthesis, if there are different number of spaces it doesn’t work. Plus you use an OR, so the second part of the regex is checked only if the first part matches nothing, so, the \1 will match zero spaces because it match exactly what was in the round parenthesis…
/^(\s+)|\1$/g - is globally looking for anything that matches either of two conditions (example) - where the two conditions are singly:
one or more spaces at the beginning (example)
Since there’s an or (|), if you find a match that has one or more spaces at the beginning (’ ^\s+'), then that matched text won’t be evaluated by the second portion of the regex.
one or more spaces at the end (example)
Unlike the back reference, this condition isn’t based on any existing capture group; it can match things all by itself and is no way dependent on the first condition.
Here’s a rough javascript analogy:
let startStringMatch = false
let endStringMatch = true
// /^(\s+)|\1$/g is like this:
let either = startStringMatch || endStringMatch
console.log('either:', either)
// /^\s+|\s+$/g is like this:
let backmatch = startStringMatch || endStringMatch === startStringMatch
console.log('backmatch', backmatch)