32 votes

Pourquoi des pseudos fonctionnels tels que: not () et: has () autorisent-ils les arguments cités?

Apparemment, comme je l'ai découvert en commentant une autre réponse, jQuery (plutôt sous-jacentes du sélecteur moteur de Grésillement) permet de citer l'argument de l' :not() sélecteur ainsi que l' :has() - sélecteur. À savoir:

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

Dans les Sélecteurs standard, les citations sont toujours représentatifs d'une chaîne et d'un sélecteur ou d'un mot clé, de sorte citant l'argument :not() est toujours valide. Cela ne changera pas dans les Sélecteurs 4.

Vous pouvez également voir qu'il est non-standard de la syntaxe par l'ajout d'une non prise en charge sélecteur CSS comme :nth-last-child(1) origine du sélecteur de panne complète:

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

Est-il une bonne raison, techniques ou autres, pour permettre à des citations ici? Les seules possibilités qui viennent à l'esprit sont:

  • La cohérence avec d' :contains() qui permet à la fois cotées ou non les arguments, comme on le voit dans les vieux Sélecteurs spec. Sauf :contains() accepte les chaînes de caractères/mots-clés, pas de sélecteurs...

  • La cohérence avec la mise en œuvre de la coutume, en utilisant les pseudos $.expr[':'], ce qui permet toujours cotées et non cotées arguments.

  • La cohérence et la facilité de portage à leur méthode homologues .not() et .has() (seulement de supprimer ou de scission de l'extérieur des guillemets et le changement des deux points de périodes?).

Mais je ne trouve pas de sources de soutenir ou de s'opposer à eux. En fait, la capacité de devis sélecteur arguments lui-même n'est pas documenté nulle part, il ne semble pas y avoir de différence entre citer et de ne pas citer l'argument:

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

30voto

Will Palmer Points 2614

Ce n'est pas spécifique à l' :not(...) et :has(...) sélecteurs - en fait, tous les pseudos dans Grésillement permettre la cité des arguments. Le modèle pour les pseudos arguments est défini comme:

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

Qui peuvent être trouvés en ligne 91 de sizzle.js de 831c9c48...

Nous allons ajouter un peu en retrait pour que, pour le rendre un peu plus lisible. Malheureusement, c'est encore une regexp, donc "un peu plus lisible" encore laisse beaucoup à désirer:

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

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

            "|" + // - OR -

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

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

Le principal de ce est: simple ou double-guillemets peuvent être utilisé autour de l'argument dans une pseudo-attribut. La barre oblique inverse est s'échapper d'être correctement gérée, et si toute chaîne de caractères arbitraire pourrait être transmis sous la forme d'un argument. Notez que la "chaîne" de la partie vents dans le même match index le "sélecteur" dans le cadre ci-dessus regexp; donc, en résumé, c'est pourquoi ils sont traités de manière égale: parce que l' pseudos modèle ne prend pas en la distinction entre les deux. edit: comme de jQuery 1.8.2, les arguments avec et sans les guillemets sont plus explicitement équivalent. Je n'arrive pas pour trouver ce code dans le jQuery, git [aide serait appréciée], mais la version de 1.8.2 hébergé par google, d'avoir le sha1sum de a0f48b6ad5322b35383ffcb6e2fa779b8a5fcffc, a un "PSEUDO": de la fonction sur la ligne 4206, ce qui ne explicitement détecter un la différence entre la "cité" et "non cotées" arguments, et veille à ce qu'ils les deux se retrouvent dans le même lieu. Cette logique ne pasdistinguer entre le type de pseudo ("position" ou non) dont l'argument est pour.

Comme le Grésillement utilise les chaînes de caractères Javascript pour lancer le processus de sélection, il n'y a pas de distinction entre la "chaîne" et "sélecteur" lorsque les arguments sont transmises à des fonctions. Faire ce genre de distinction serait possible, mais autant que je suis conscient, ce qui est réellement désiré est toujours facilement déterminé à partir de la base de contexte (c'est à dire: de quel type de le pseudo est utilisé), donc il n'y a pas de véritable raison de faire de l' la distinction. (merci de corriger dans les commentaires si il y a aucune ambigu situations où je ne suis pas au courant de l' - j'aimerais bien le savoir!).

Alors, si l'absence de distinction entre les cordes et les sélecteurs est un mise en œuvre simple détail, pourquoi ne les pseudos tels que :eq(...)explicitement rejeter ces sélections?

La réponse est simple: il n'a pas, vraiment. Au moins, pas de jQuery 1.8.1. [edit: comme de jQuery 1.8.2, il n'est pas du tout. Les arguments de "positionnel" les pseudos peuvent être cités comme rien d'autre. Ci-dessous notes concernant les détails de mise en œuvre de 1.8.1 sont à gauche comme un curiosité historique]

Des fonctions telles que :eq(...) sont mis en œuvre comme:

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

Au moment de l' :eq(...) reçoit de l'argument, il est toujours dans le forme d'un simple argument (les citations et tout et tout). Contrairement aux :not(...), ce l'argument de ne pas passer par un compile(...) de phase. Le "rejet" de l'argument non valide est en réalité le raccourci de moulage par +argument, ce qui entraînera NaN pour toute chaîne de caractères entre guillemets (ce qui, dans tour, ne correspond jamais avec quoi que ce soit). C'est encore une autre mise en œuvre le détail, même si dans ce cas un "correctement" de se comporter l'un (de nouveau, dans la mesure du comme je suis au courant. Existe-il des situations où des non-arguments numériques à ces les fonctions doivent en effet correspondre?)

edit: Comme de jQuery 1.8.2, les Choses ont été quelque peu remaniée, et "positionnel" les pseudos ne sont plus recevoir le "raw" argument. Comme un résultat, cité arguments sont maintenant acceptées en :eq(...) et la comme. Ce changement semble avoir été un effet secondaire d'une autre correction, car il y est fait aucune mention du soutien pour la cité des arguments dans le changelog pour af8206ff.., qui vise à corriger une erreur dans la manipulation d' :first et :last, jQuery bug #12303. Ce commit a été trouvé à l'aide de git bisect et relativement simple phantomjs script. Il est à noter que, après le Grésillement de réécriture dans e89d06c4.., Grésillement ne serait pas simplement silencieuse pour les sélecteurs comme :eq("3"), il serait effectivement de lever une exception. Qui doit être pris encore plus de preuves qu' :eq("3") support n'est pas prévu de comportement.

Il y a en effet des justifications au sujet des filtres personnalisés, dont les arguments pourrait dans certains cas être considérés comme des chaînes de caractères, et parfois en tant que sélecteurs, peu importe ce qu'ils superficiellement ressembler, selon la méthode dans laquelle ils sont évalués... mais que l'on est en approche le pédant. Il devrait suffire de dire que ne pas avoir de distinction au moins rend les choses plus simples lors de l'appel de fonctions qui, en aucun importe ce qu'ils peuvent représenter, s'attendre à une représentation sous forme de chaîne.

En bref, la situation dans son ensemble peut être considéré comme une mise en œuvre détail, et est enracinée dans le fait que les sélecteurs sont passés comme les chaînes en premier lieu (sinon, comment voulez-vous obtenir dans Grésillement?).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X