32

どうやら、私が別の答えにコメントしているときに発見したように、jQuery(その基礎となるセレクターエンジンSizzle:not() )を使用すると、セレクターだけでなくセレクターへの引数を引用できます:has()ウィットに

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

Selectors標準では、引用符は常に文字列を表し、セレクターやキーワードを表すことはないため、引数を引用符で囲むことは:not()常に無効です。これはセレクター4では変更されません。

また、セレクターを完全に失敗させるなど、サポートされていないCSSセレクターを追加することで、非標準の構文であることがわかります。:nth-last-child(1)

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

ここで見積もりを許可する理由は、技術的であろうとなかろうと、何かありますか?頭に浮かぶ唯一の可能性は次のとおりです。

  • 古いセレクターの仕様:contains()に見られるように、引用符で囲まれた引数と引用符で囲まれていない引数の両方を許可する一貫性。セレクターではなく、文字列/キーワードを受け入れることを除いて...:contains()

  • を使用したカスタム疑似の実装との一貫性$.expr[':']。これにより、引用符で囲まれた引数と引用符で囲まれていない引数が常に許可されます。

  • 対応するメソッドへの一貫性と移植の容易さ.not().has()外側の引用符を削除または分割し、コロンをピリオドに変更するだけですか?)。

しかし、私はそれらを支持または反対する情報源を見つけることができません。実際、セレクター引数自体を引用する機能はどこにも文書化されておらず、引数を引用することと引用しないことの間に違いはないようです。

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

1 に答える 1

30

これはセレクターに固有のものではありません:not(...):has(...)実際、Sizzleのすべての疑似は引用符で囲まれた引数を許可します。疑似引数のパターンは次のように定義されます。

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

時点での行で見つけることができます91sizzle.js831c9c48...

少し読みやすくするために、それにインデントを追加しましょう。残念ながら、これはまだ正規表現であるため、「もう少し読みやすい」ということには、まだ多くの要望があります。

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

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

            "|" + // - OR -

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

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

これからの主なポイントは次のとおりです。疑似属性の引数の前後に一重引用符または二重引用符を使用できます。バックスラッシュのエスケープは適切に処理されるため、任意の文字列を引数として渡すことができます。「文字列」の部分は、上記の正規表現の「セレクター」の部分と同じ一致インデックスになります。つまり、要するに、それがそれらが同等に扱われる理由ですpseudos。パターンが2つを区別しないためです。編集: jQuery 1.8.2以降、引用符のある引数とない引数は、より明示的に同等です。jQuery gitリポジトリでこのコードを見つけることができないようです[ヘルプをいただければ幸いです]が、a0f48b6ad5322b35383ffcb6e2fa779b8a5fcffcのsha1sumを持つgoogleによってホストされているバージョン1.8.2にはオンラインで機能 "PSEUDO":があります4206、「引用符で囲まれた」引数と「引用符で囲まれていない」引数の違いを明示的に検出し、両方が同じ場所に配置されるようにします。このロジックは、引数の対象となる疑似のタイプ(「位置」かどうか)を区別しません。

SizzleはJavascript文字列を使用して選択プロセスを開始するため、引数が関数に渡されるときに「文字列」と「セレクター」の区別はありません。そのような区別をすることは可能ですが、私が知る限り、実際に何が望まれるかは、最も基本的なコンテキスト(つまり、どのタイプの疑似が使用されているか)から常に簡単に決定されるため、区別します。(私が気付いていないあいまいな状況がある場合は、コメントで修正してください-知りたいです!)

それでは、文字列とセレクターの区別がないことが単なる実装の詳細である場合、なぜその:eq(...)ような選択を明示的に拒否するなどの疑似が行われるのでしょうか。

答えは簡単です。実際にはそうではありません。少なくとも、jQuery1.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引用符で囲まれた文字列が生成されます(これにより、何にも一致しなくなります)。これはさらに別の実装の詳細ですが、この場合は「正しく」動作します(ここでも、私が知る限り、そのような関数に対する非数値引数が実際に一致する必要がある状況はありますか?)

編集: jQuery 1.8.2の時点で、物事は多少リファクタリングされており、「位置」疑似は「生」引数を受け取らなくなりました。その結果、引用符で囲まれた引数がなどで受け入れられる:eq(...)ようになりました。この変更は、別のバグ修正の副作用であるように見えます。これは、 af8206ff ..の変更ログに引用符で囲まれた引数のサポートが記載されていないためです。これはjQueryのバグ#12303の処理エラー:first:lastを修正することを目的としています。このコミットは、git bisect比較的単純なphantomjsスクリプトを使用して検出されました。e89d06c4でSizzleを書き直した後、Sizzleが次のようなセレクターに対して単にサイレントに失敗するわけではないことは注目に値します。:eq("3")、実際には例外がスローされます。:eq("3")これは、サポートが意図された動作ではないというさらに多くの証拠と見なされるべきです。

カスタムフィルターに関しては確かに論理的根拠があり、その引数は、評価される方法に応じて、表面的にどのように見えても、場合によっては文字列、場合によってはセレクターと見なすことができます...しかし、その多くは近づいています衒学者。少なくとも区別がないことで、文字列表現を期待する関数を呼び出すときに、物事が簡単になると言えば十分です。

要するに、全体の状況は実装の詳細と考えることができ、セレクターが最初に文字列として渡されるという事実に根ざしています(他にどのようにそれらをSizzleに入れるのですか?)。

于 2012-09-19T22:47:15.920 に答える