Apparently, as I've discovered while commenting on another answer, jQuery (rather its underlying selector engine Sizzle) lets you quote the argument to the :not()
selector as well as the :has()
selector. To wit:
显然,正如我在评论另一个答案时发现的那样,jQuery(而不是它的底层选择器引擎Sizzle)允许您引用:not()选择器以及:has()选择器的参数。即:
$('div:not("span")')
$('span:has("span")')
In the Selectors standard, quotes are always representative of a string and never of a selector or a keyword, so quoting the argument to :not()
is always invalid. This will not change in Selectors 4.
在选择器标准中,引号总是代表字符串,而不是选择器或关键字,所以引用参数to:not()总是无效的。这在选择器4中不会改变。
You can also see that it's non-standard syntax by adding an unsupported CSS selector such as :nth-last-child(1)
causing the selector to fail completely:
您还可以通过添加不支持的CSS选择器(例如:nth-last-child(1))来看到它是非标准语法,从而导致选择器完全失败:
$('div:not("span"):nth-last-child(1)')
$('span:has("span"):nth-last-child(1)')
Is there any good reason, technical or otherwise, for allowing quotes here? The only possibilities that come to mind are:
是否有什么好的理由允许在这里引用,无论是技术上的还是其他的?我唯一想到的可能性是:
-
Consistency with
:contains()
which allows both quoted and unquoted arguments, as seen in the old Selectors spec. Except:contains()
accepts strings/keywords, not selectors...与:contains()保持一致,它允许引用和不引用的参数,就像在旧的选择器规范中看到的那样。
-
Consistency with the implementation of custom pseudos using
$.expr[':']
, which always allows quoted and unquoted arguments.与使用$的定制pseudo的实现一致。expr[':'],它总是允许引用和不引用的参数。
-
Consistency and ease of porting to their method counterparts
.not()
and.has()
(just remove or split the outer quotes and change colons to periods?).将它们的方法对应物.not()和.has()移植到它们的方法副本的一致性和简便性(只需删除或分割外部引号并将冒号改为句点?)
But I can't find any sources to support or oppose them. In fact, the ability to quote selector arguments itself isn't documented anywhere either, nor does there appear to be any difference between quoting and not quoting the argument:
但我找不到任何支持或反对他们的来源。事实上,引用选择器参数本身的能力在任何地方都没有记录,引用和不引用参数之间也没有任何区别:
$('div:not(span)')
$('span:has(span)')
1 个解决方案
#1
30
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:
这不是特定于:not(…)和:has(…)选择器—实际上,Sizzle中的所有pseudo允许引用参数。伪参数的模式定义为:
pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)"
Which can be found on line 91
of sizzle.js
as of 831c9c48...
可以在sizzle的第91行找到。js截至831年c9c48……
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:
让我们添加一些缩进,使它更容易读。不幸的是,这仍然是一个regexp,因此“更易于阅读”仍然有很多需要改进的地方:
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.
从中得到的主要结论是:单引号或双引号都可以用于伪属性中的参数。反斜杠转义是正确处理的,因此任何任意的字符串都可以作为参数传入。注意,“字符串”部分最终与上面regexp中的“选择器”部分相同;因此,简而言之,这就是为什么他们被平等对待:因为伪模式没有区分两者。编辑:在jQuery 1.8.2中,带引号和不带引号的参数更显式地等效。我似乎无法找到这段代码在jQuery git存储库中(帮助不胜感激),但1.8.2由谷歌的版本,有a0f48b6ad5322b35383ffcb6e2fa779b8a5fcffc sha1sum,有一个“伪”:函数在第4206行,它明确地发现区别“引用”和“非挂牌”的论点,并确保他们都在同一个地方结束。这个逻辑没有区分参数所支持的伪(“位置”或“非位置”)类型。
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!).
由于Sizzle使用Javascript字符串启动选择过程,当参数传递给函数时,“string”和“selector”之间没有区别。做出这种区分是可能的,但就我所知,真正想要的东西总是很容易由最基本的上下文(例如:使用的是什么类型的伪)来决定,所以没有真正的理由去区分它们。(如有不清楚的情况,请在评论中更正,我很想知道!)
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?
那么,如果字符串和选择器之间缺乏区别只是实现细节,那么为什么像:eq(…)这样的伪函数会明确地拒绝这些选择呢?
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]
答案很简单:实际上不是。至少在jQuery 1.8.1中没有。[编辑:就jQuery 1.8.2而言,它根本不是。“位置”伪命题的参数可以像其他任何东西一样被引用。关于1.8.1的实现细节,下面的注释作为历史的好奇之处留下]
Functions such as :eq(...)
are implemented as:
eq(…)等功能实现如下:
"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?)
当:eq(…)接收到这个参数时,它仍然是一个简单的参数(引用和所有)。不像:not(…),这个参数不经过编译(…)阶段。无效参数的“拒绝”实际上是由于通过+参数的短选,这将导致对任何引用字符串的NaN(反过来,永远不匹配任何东西)。这是另一个实现细节,尽管在这种情况下,一个“正确”的行为(就我所知,也是如此)。是否存在这样的函数的非数字参数实际上应该匹配的情况?)
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.
编辑:从jQuery 1.8.2开始,事情有所重构,“位置”伪函数不再接收“原始”参数。因此,引用的参数现在可以在eq(…)等中接受。这个更改似乎是另一个错误修复的副作用,因为没有提到对af8206ff的changelog中引用的参数的支持。,用于修复处理中的错误:first和:last, jQuery bug #12303。使用git二段和一个相对简单的phantomjs脚本找到这个提交。值得注意的是,在e89d06c4的Sizzle重写之后。, Sizzle不仅仅是对选择器(如:eq(“3”)的无声失败,它实际上会抛出一个异常。这应该被视为更多的证据:eq(“3”)支持并不是有意的行为。
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?).
简而言之,整个场景可以被视为实现细节,其根源在于选择器首先作为字符串传递(否则如何让它们进入Sizzle呢?)
#1
30
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:
这不是特定于:not(…)和:has(…)选择器—实际上,Sizzle中的所有pseudo允许引用参数。伪参数的模式定义为:
pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)"
Which can be found on line 91
of sizzle.js
as of 831c9c48...
可以在sizzle的第91行找到。js截至831年c9c48……
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:
让我们添加一些缩进,使它更容易读。不幸的是,这仍然是一个regexp,因此“更易于阅读”仍然有很多需要改进的地方:
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.
从中得到的主要结论是:单引号或双引号都可以用于伪属性中的参数。反斜杠转义是正确处理的,因此任何任意的字符串都可以作为参数传入。注意,“字符串”部分最终与上面regexp中的“选择器”部分相同;因此,简而言之,这就是为什么他们被平等对待:因为伪模式没有区分两者。编辑:在jQuery 1.8.2中,带引号和不带引号的参数更显式地等效。我似乎无法找到这段代码在jQuery git存储库中(帮助不胜感激),但1.8.2由谷歌的版本,有a0f48b6ad5322b35383ffcb6e2fa779b8a5fcffc sha1sum,有一个“伪”:函数在第4206行,它明确地发现区别“引用”和“非挂牌”的论点,并确保他们都在同一个地方结束。这个逻辑没有区分参数所支持的伪(“位置”或“非位置”)类型。
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!).
由于Sizzle使用Javascript字符串启动选择过程,当参数传递给函数时,“string”和“selector”之间没有区别。做出这种区分是可能的,但就我所知,真正想要的东西总是很容易由最基本的上下文(例如:使用的是什么类型的伪)来决定,所以没有真正的理由去区分它们。(如有不清楚的情况,请在评论中更正,我很想知道!)
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?
那么,如果字符串和选择器之间缺乏区别只是实现细节,那么为什么像:eq(…)这样的伪函数会明确地拒绝这些选择呢?
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]
答案很简单:实际上不是。至少在jQuery 1.8.1中没有。[编辑:就jQuery 1.8.2而言,它根本不是。“位置”伪命题的参数可以像其他任何东西一样被引用。关于1.8.1的实现细节,下面的注释作为历史的好奇之处留下]
Functions such as :eq(...)
are implemented as:
eq(…)等功能实现如下:
"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?)
当:eq(…)接收到这个参数时,它仍然是一个简单的参数(引用和所有)。不像:not(…),这个参数不经过编译(…)阶段。无效参数的“拒绝”实际上是由于通过+参数的短选,这将导致对任何引用字符串的NaN(反过来,永远不匹配任何东西)。这是另一个实现细节,尽管在这种情况下,一个“正确”的行为(就我所知,也是如此)。是否存在这样的函数的非数字参数实际上应该匹配的情况?)
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.
编辑:从jQuery 1.8.2开始,事情有所重构,“位置”伪函数不再接收“原始”参数。因此,引用的参数现在可以在eq(…)等中接受。这个更改似乎是另一个错误修复的副作用,因为没有提到对af8206ff的changelog中引用的参数的支持。,用于修复处理中的错误:first和:last, jQuery bug #12303。使用git二段和一个相对简单的phantomjs脚本找到这个提交。值得注意的是,在e89d06c4的Sizzle重写之后。, Sizzle不仅仅是对选择器(如:eq(“3”)的无声失败,它实际上会抛出一个异常。这应该被视为更多的证据:eq(“3”)支持并不是有意的行为。
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?).
简而言之,整个场景可以被视为实现细节,其根源在于选择器首先作为字符串传递(否则如何让它们进入Sizzle呢?)