Why do functional pseudos such as :not() and :has() allow quoted arguments?

2018-04-16 admin

CommunityBoltClock提出了一个问题:Why do functional pseudos such as :not() and :has() allow quoted arguments?,或许与您遇到的问题类似。

回答者Will Palmer给出了该问题的处理方式:

This isn’t specific to :not(...) and :has(...) selectors- actually, all pseudos in Sizzle allow for quoted arguments. The pattern for pseudos’ arguments is defined as:

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

Which can be found on line 91 of sizzle.js as of 831c9c48...

Let’s add some indentation to that, to make it a bit more readable. Unfortunately, this is still a regexp, so “a bit more readable” still leaves a lot to be desired:

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

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

            "|" + // - OR -

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

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

The main take-away from this is: either single or double-quotes can be used around the argument in a pseudo-attribute. Backslash escaping is properly handled, and so any arbitrary string could be passed in as an argument. Note that the “string” part winds up in the same match index as the “selector” part in the above regexp; so, in short, that is why they are treated equally: because the pseudos pattern does not distinguish between the two. edit: as of jQuery 1.8.2, arguments with and without quotes are more-explicitly equivalent. I cannot seem to find this code in the jQuery git repository [help would be appreciated], but the version of 1.8.2 hosted by google, having the sha1sum of a0f48b6ad5322b35383ffcb6e2fa779b8a5fcffc, has a "PSEUDO": function on line 4206, which does explicitly detect a difference between “quoted” and “unquoted” arguments, and ensures they both wind up in the same place. This logic does not distinguish between the type of pseudo (“positional” or not) which the argument is for.

As Sizzle uses Javascript strings to kick off the selection process, there is no distinction between “string” and “selector” when arguments are passed in to functions. Making that kind of distinction would be possible, but as far as I am aware, what is actually desired is always easily determined from the most basic of context (ie: what type of pseudo is being used), so there is no real reason to make the distinction. (please correct in comments if there are any ambiguous situations which I am unaware of- I’d like to know!).

So then, if the lack of distinction between strings and selectors is a mere implementation detail, why do pseudos such as :eq(...) explicitly reject such selections?

The answer is simple: it doesn’t, really. At least, not as of jQuery 1.8.1. [edit: as of jQuery 1.8.2, it doesn’t at all. The arguments of “positional” pseudos can be quoted just like anything else. The below notes regarding the implementation details of 1.8.1 are left as a historical curiosity]

Functions such as :eq(...) are implemented as:

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

At the time that :eq(...) receives the argument, it is still in the form of a bare argument (quotes and all). Unlike :not(...), this argument doesn’t go through a compile(...) phase. The “rejection” of the invalid argument is actually due to the shortcut-casting via +argument, which will result in NaN for any quoted string (which in turn, never matches anything). This is yet another implementation detail, though in this case a “correctly” behaving one (again, as far as I am aware. Are there situations where non-numeric arguments to such functions should in fact match?)

edit: As of jQuery 1.8.2, Things have been refactored somewhat, and “positional” pseudos no-longer receive the “raw” argument. As a result, quoted arguments are now accepted in :eq(...) and the like. This change appears to have been a side-effect of another bugfix, as there is no mention of support for quoted arguments in the changelog for af8206ff…, which was intended to fix an error in handling :first and :last, jQuery bug #12303. This commit was found using git bisect and a relatively simple phantomjs script. It is notable that after the Sizzle rewrite in e89d06c4…, Sizzle would not merely fail silently for selectors such as :eq("3"), it would actually throw an exception. That should be taken as yet more evidence that :eq("3") support is not intended behaviour.

There are indeed rationales regarding custom filters, whose arguments could in some cases be thought of as strings, and sometimes as selectors, no matter what they superficially look like, depending on the method in which they are evaluated… but that much is approaching the pedantic. It should suffice to say that not having a distinction at the least makes things simpler when calling functions which, no matter what they may represent, expect a string representation.

In short, the whole situation can be thought of as an implementation detail, and is rooted in the fact that selectors are passed around as strings in the first place (how else would you get them into Sizzle?).




转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]


文章标题: Why do functional pseudos such as :not() and :has() allow quoted arguments?

简介: 《Effective JavaScript:编写高质量JavaScript代码的68个有效方法》共分为7章,分别涵盖JavaScript的不同主题。第1章主要讲述最基本的主题,如版本、类型转换要点、运算符注意事项和分号局限等。第2章...
《Ajax 从入门到精通》PDF
简介: Ajax 由 HTML、java script™ 技术、DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序。本系列的作者是一位 Ajax 专家,他演示了这些技术如何协同工作 ——...
简介: 本书是为从未接触过HTML5新技术但同时又对移动web技术感兴趣的读者而编写的。如果你有一定的HTML开发经验,将会更容易掌握HTML5知识。本书共分为四大部分,第一部分主要讲述Web技术的发展及HTML5标准在移动Web技术中的应...
《JavaScript完全自学手册》 javascript是一种几乎得到所有浏览器支持的脚本语言,用于实现客户端与浏览者的互动。随着互联网的发展,早期的静态网页已远不能满足需要。客户端脚本javascript是实现动态网页的基础,也是web...
《JavaScript学习指南(第2版)》通过列举JavaScript应用的最佳实践和示例,本书展示了如何将该语言集成到浏览器环境中,及如何在符合标准的网站中应用这些已通过实践验证的编码技术。 本书内容: ● JavaScript应用程序的...
《HTML 5实战》是一本系统而全面的HTML 5教程,根据HTML 5标准的最新草案,系统地对HTML 5的所有重要知识点进行了全面的讲解。在写作方式上,本书以一种开创性的方式使理论与实践达到极好的平衡,不仅对理论知识进行了清晰而透彻的阐...