IE не так. В ECMAScript только одна альтернатива может привести к строке. Все остальные должны быть undefined
(не ""
или что-то еще).
Таким образом, для ваших альтернатив, включая (transform[^-][^;}]+)|(transform-origin[^;}]+)
, Firefox и Chrome верны в установке неудачного захвата на undefined
.
В стандарте ECMAScript 5 (§15.10.2.3) есть пример, касающийся этого:
ПРИМЕЧАНИЕ. | оператор регулярного выражения
разделяет две альтернативы.
шаблон сначала пытается соответствовать левому
Альтернатива (с последующим продолжением
регулярное выражение); если не получится,
он пытается соответствовать правильному
Дизъюнкция (с последующим продолжением
регулярное выражение). Если слева
Альтернатива, правильное дизъюнкция,
и продолжение у всех есть точки выбора,
все варианты в продолжении испробованы
прежде чем перейти к следующему выбору в
левая альтернатива. Если выбор в
левая альтернатива исчерпана,
вместо этого пробуется правильное дизъюнкция
левой альтернативы. Любой захват
скобки внутри части
шаблон пропущен | производить неопределенный
значения вместо строк.
Таким образом, для
Например, /a|ab/.exec("abc ") возвращает
результат «а», а не «ab». Более того,
/((a)|(ab))((c)|(bc))/.exec("abc ")
возвращает массив ["abc", "a", "a",
undefined, "bc", undefined, "bc"] и
not ["abc", "ab", undefined, "ab",
"c", "c", не определено]
РЕДАКТИРОВАТЬ: Я понял последнюю часть. Это относится как к оригинальной, так и к упрощенной версии. В обоих случаях rule1
и rule2
не могут совпадать с ;
(в оригинале, поскольку ;
относится к классу отрицанных символов [^;}]
). Таким образом, когда между объявлениями появляется ;
, чередование выбирает [^}]
. Таким образом, он должен установить последние два захвата на undefined
.
Чтобы *
был полностью жадным, конечный ;
и пробел на входе также должны совпадать. Для последних двух *
повторений (';' и '') чередование снова выбирает [^}]
, поэтому в конце также должны быть установлены захваты undefined
.
IE не может сделать это в обоих случаях, поэтому они остаются равными "rule1" и "rule2".
Наконец, причина, по которой второй пример ведет себя по-разному, заключается в том, что (transform-origin[^;}]+))
соответствует самому последнему *
повторению, поскольку до конца нет ;
.
РЕДАКТИРОВАТЬ 2: Я буду проходить через то, что должно происходить в обоих текущих примерах. match
- массив совпадений.
var str="#rot { rule1; rule2; }";
var patt=/.*?(rule1|rule2)(?:(rule1|rule2)|[^}])*/i;
.*? - "#rot { "
(rule1|rule2) - "rule1"
match[1] = "rule1"
Звезда 1
[^}] - ";"
match[2] = undefined
Звезда 2
[^}] - " "
match[2] = undefined
Звезда 3
(rule1|rule2) - "rule2"
match[2] = "rule2"
Звезда 4
[^}] - ";"
match[2] = undefined
Звезда 5
[^}] - " "
match[2] = undefined
Опять же, IE не устанавливает соответствие [2] на undefined
.
Для примера str.match
вы используете глобальный флаг. Это означает, что он возвращает массив совпадений без перехватов. Это относится к любому использованию String.match
. Если вы используете g
, вы должны использовать exec для получения снимков.
var str="#rot { rule1; rule2 }";
var patt=/.*?(rule1|rule2)(?:(rule1 |rule2 )|[^}])*/gi;
.*? - "#rot { "
(rule1|rule2) - "rule1"
match[1] = "rule1"
Звезда 1
[^}] - ";"
match[2] = undefined
Звезда 2
[^}] - " "
match[2] = undefined
Звезда 3
(rule1 |rule2 ) - "rule2 "
match[2] = "rule2 "
Поскольку это последний *
, для захвата никогда не устанавливается неопределенное значение.