Подтвердить что ты не робот

Почему функциональные псевдо, такие как: not() и: имеют() разрешают цитируемые аргументы?

По-видимому, как я обнаружил, комментируя еще один ответ, jQuery (скорее, его основной механизм выбора Sizzle) позволяет привести аргумент в селектор :not(), а также селектор :has(). Для остроумия:

$('div:not("span")')
$('span:has("span")')

В Селекторах стандарта кавычки всегда представляют собой строку и никогда не относятся к селектору или ключевому слову, поэтому цитирование аргумента :not() всегда недействителен. Это не изменится в Селекторах 4.

Вы также можете увидеть, что это нестандартный синтаксис, добавив неподдерживаемый CSS-селектор, например :nth-last-child(1) в результате чего селектор полностью завершится:

$('div:not("span"):nth-last-child(1)')
$('span:has("span"):nth-last-child(1)')

Есть ли веская причина, техническая или иная, для предоставления котировок здесь? Единственные возможности, которые приходят на ум, - это:

  • Согласованность с :contains(), которая позволяет использовать как цитируемые, так и неуказанные аргументы, как показано в старой спецификации Selectors. За исключением :contains() принимает строки/ключевые слова, а не селекторы...

  • Согласованность с реализацией пользовательских псевдостей с использованием $.expr[':'], которая всегда позволяет использовать котируемые и некотируемые аргументы.

  • Согласованность и простота переноса на их копии методов .not() и .has() (просто удалите или разделите внешние кавычки и измените двоеточие на периоды?).

Но я не могу найти никаких источников для поддержки или против них. Фактически, возможность цитирования самих селекторных аргументов нигде не документируется, и не существует никакой разницы между цитированием и не цитированием аргумента:

$('div:not(span)')
$('span:has(span)')
4b9b3361

Ответ 1

Это не относится к селекторам :not(...) и :has(...) - фактически, все псевдосты в Sizzle разрешают цитируемые аргументы. Шаблон для аргументов псевдода определяется как:

pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)"

Что можно найти в строке 91 of sizzle.js от 831c9c48...

Добавьте некоторые отступы к этому, чтобы сделать его более читаемым. К сожалению, это все еще регулярное выражение, поэтому "немного более читаемый" все еще оставляет желать лучшего:

pseudos = (
    ":(" + characterEncoding + ")" +
    "(?:" +
    "\\(" + // literal open-paren
        "(?:" +

                "(['\"])" + // literal open-quote
                    "((?:\\\\.|[^\\\\])*?)" + // handle backslash escaping
                "\\2" + // close-quote

            "|" + // - OR -

                "(" +
                    "[^()[\\]]*" +
                    "|" +
                    "(?:" +
                        "(?:" + attributes + ")" +
                        "|" +
                        "[^:]" +
                        "|" +
                        "\\\\." +
                    ")*" +
                    "|" +
                    ".*" +
                ")" +

        ")" +
    "\\)" + // literal close-paren
    "|" + // ie, 'or nothing'
")"
);

Основной отрыв от этого: либо одиночные, либо двойные кавычки могут быть используется вокруг аргумента в псевдоатрибуте. Выпадение обратной косой черты правильно обработаны, и поэтому любая произвольная строка может быть передана как аргумент. Обратите внимание, что часть "строка" завершается в том же индексе соответствия как часть "селектора" в вышеуказанном регулярном выражении; так, короче говоря, вот почему их обрабатывают одинаково: поскольку шаблон pseudos не различают эти два. изменить: по jQuery 1.8.2, аргументы с кавычками и без них более явно эквивалентны. Я не могу показаться найти этот код в репозитории jQuery git [помощь будет оценена], но версия 1.8.2, размещенный google, имеющий sha1sum a0f48b6ad5322b35383ffcb6e2fa779b8a5fcffc, имеет "PSEUDO": в строке 4206, которая явно обнаруживает различие между аргументами "цитируемый" и "нецитированный" и обеспечивает их оба заканчиваются в одном и том же месте. Эта логика отличает не между типом псевдо ( "позиционный" или нет), который аргумент для.

Как Sizzle использует строки Javascript, чтобы начать процесс выбора, нет различия между "строкой" и "селектором", когда аргументы передаются в функции. Такое различие было бы возможно, но, насколько мне известно, то, что действительно желательно, всегда легко определяется из самого основного контекста (то есть: какой тип pseudo), поэтому нет реальной причины сделать различие. (пожалуйста, исправьте в комментариях, если есть какие-то двусмысленные ситуации, о которых я не знаю - я хотел бы знать!).

Итак, если отсутствие различия между строками и селекторами является просто детали реализации, почему псевдовы, такие как :eq(...) явно отклонить такие выборы?

Ответ прост: на самом деле это не так. По крайней мере, не как jQuery 1.8.1. [ изменить: по состоянию на jQuery 1.8.2, это совсем не так. Аргументы "Позиционные" псевдонимы могут быть процитированы так же, как и все остальное. Нижеприведенное примечания относительно деталей реализации 1.8.1 остаются в виде историческое любопытство]

Функции, такие как :eq(...), реализованы как:

"eq": function( elements, argument, not ) {
    var elem = elements.splice( +argument, 1 );
    return not ? elements : elem;
}

В то время, когда :eq(...) получает аргумент, он все еще находится в форма голого аргумента (кавычки и все). В отличие от :not(...), это аргумент не проходит через фазу compile(...). "Отказ" неверный аргумент на самом деле связан с ярлыком с помощью +argument, что приведет к NaN для любой цитируемой строки (которая в поворот, никогда не соответствует чему-либо). Это еще одна реализация подробно, хотя в этом случае "правильно" ведет себя (опять же, как далеко как мне известно. Существуют ли ситуации, когда нечисловые аргументы для таких функции должны совпадать?)

edit: Как и в jQuery 1.8.2, вещи были несколько реорганизованы, и "Позиционные" псевдонимы больше не принимают "сырой" аргумент. В результате, приведенные аргументы теперь принимаются в :eq(...) и т.п. Это изменение похоже, был побочным эффектом другого исправления, поскольку упоминания о поддержке цитируемых аргументов в журнале изменений для af8206ff.., который был предназначен для исправления ошибки при обработке :first и :last, ошибки jQuery # 12303. Эта фиксация была найдена с использованием git bisect и относительно простых фантомов script. Примечательно, что после перезаписи Sizzle в e89d06c4.. Sizzle не просто терпит неудачу для селекторов, таких как :eq("3"), это на самом деле выбросить исключение. Это должно быть еще больше доказательством того, что поддержка :eq("3") не предназначена для поведения.

Есть действительно обоснования относительно пользовательских фильтров, аргументы которых в некоторых случаях можно рассматривать как строки, а иногда как селекторов, независимо от того, что они внешне выглядят, в зависимости от метод, в котором они оцениваются... но это очень приближается педантичный. Достаточно сказать, что не имея различия по крайней мере, упрощает при вызове функции, которые нет что они могут представлять, ожидать строковое представление.

Короче говоря, всю ситуацию можно рассматривать как реализацию подробно, и уходит корнями в то, что селектора передаются как в первую очередь (как еще вы могли бы получить их в Sizzle?).