为什么:not()和:has()等函数伪函数允许引用参数?

显然,正如我在评论另一个答案时发现的,jQuery(而不是它的底层选择器引擎Sizzle)允许您引用:not()选择器以及:has()选择器的参数。也就是说:

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

在选择器标准中,引号始终代表字符串,而不是选择器或关键字,因此将参数引用到:not()总是无效的。这在选择器4中不会改变

您还可以通过添加不受支持的CSS选择器(如:nth last child(1))来查看它的非标准语法,从而导致选择器完全失败:

$('div:not(“span”):第n个最后一个孩子(1)'))
$('span:has(“span”):第n个最后的子项(1)')

在这里允许报价有什么好的理由,技术上的还是其他的?我想到的唯一可能性是:

  • :contains()的一致性,它允许带引号和不带引号的参数,如旧的选择器规范所示。除了:contains()接受字符串/关键字,而不是选择器

  • 与使用$.expr[':']实现自定义伪码的一致性,该伪码始终允许带引号和不带引号的参数

  • 一致性和易于移植到方法对应项.not().has()(只需删除或拆分外部引号并将冒号更改为句点?)

但我找不到任何支持或反对他们的来源。事实上,引用选择器参数本身的能力在任何地方都没有记录,引用和不引用参数之间似乎也没有任何区别:

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

这不是特定于:不是(…):具有(…)选择器-实际上,所有的伪
在Sizzle中允许引用参数。伪参数的模式
定义如下:

pseudos=“:(“+characterEncoding+”)(((?:(['\”)(((?:\\\.[^\\\]])*?)\\2([^()[\]]*。(?:(?:“+attributes+”)[^:][^:][^:][^:][^:][^:][^\\\\\\]].])。”

可在sizzle.js91行中找到,截至831c9c48…

让我们给它添加一些缩进,让它更具可读性。
不幸的是,这仍然是一个regexp,所以“可读性更高一些”
还有很多需要改进的地方:

伪码=(
“:(“+字符编码+”)”+
"(?:" +
“\\(“+//文本打开参数
"(?:" +
“(['\“])”+//文字开引号
“(((?:\\.\\.\[^\\\])*?)”+//句柄反斜杠转义
“\\2”+//结束引号
“|”+/-或-
"(" +
"[^()[\\]]*" +
"|" +
"(?:" +
“(?:“+属性+”)”+
"|" +
"[^:]" +
"|" +
"\\\\." +
")*" +
"|" +
".*" +
")" +
")" +
“\\)“+//文本关闭参数
“|”+//即“或无”
")"
);

这样做的主要好处是:可以使用单引号或双引号
在伪属性中围绕参数使用。反斜杠转义是
正确处理,因此任何任意字符串都可以作为
论点请注意,“字符串”部分在相同的匹配索引中结束
作为上述regexp中的“选择器”部分;简言之,这就是原因
它们被同等对待:因为pseudos模式没有
区分两者编辑:从jQuery 1.8.2开始,参数
带引号和不带引号更明确地等效。我看不出来
要在jQueryGit存储库中找到这段代码[非常感谢您的帮助],但是
1.8.2由谷歌托管,sha1sum为a0f48b6ad5322b35383ffcb6e2fa779b8a5fcffc,拥有
“PSEUDO”:4206行上的函数,它明确检测
“引用”和“未引用”参数之间的差异,并确保
两者都在同一个地方。此逻辑不区分
在参数所属的伪(“位置”或非位置)类型之间
因为

Sizzle使用Javascript字符串启动选择过程,
当使用参数时,“字符串”和“选择器”之间没有区别
传递给函数。做出这样的区分是非常困难的
可能,但就我所知,真正想要的总是
从最基本的上下文(即:什么类型的
正在使用pseudo),因此没有真正的理由
区别(如有任何不明确之处,请在评论中更正
我不知道的情况-我想知道!)

因此,如果字符串和选择器之间缺乏区别是一个问题
仅仅是实现细节,为什么像:eq(…)这样的伪函数显式
拒绝这样的选择

答案很简单:事实并非如此。至少,在jQuery中不是这样
1.8.1. [edit:从jQuery 1.8.2开始,它一点也没有
“位置”伪符号可以像其他任何东西一样引用
关于1.8.1的实施细节的注释保留为
[历史好奇心]

诸如:eq(…)等功能的实现方式如下:

“eq”:函数(元素、参数、非参数){
var elem=元素。拼接(+参数,1);
是否返回?元素:elem;
}

:eq(…)收到参数时,它仍处于
纯参数的形式(引号和全部)。与:not(…)不同,此
参数没有经过编译(…)
阶段。拒绝
无效参数实际上是由于快捷方式转换导致的
+参数,对于任何带引号的字符串(在
旋转,从不匹配任何东西)。这是另一个实现
细节,尽管在本例中是一个“正确”行为的(同样,尽可能
如我所知,是否存在非数值参数用于此类
功能实际上应该匹配?

编辑:从jQuery 1.8.2开始,事情已经进行了一些重构,并且
“位置”伪对象不再接收“原始”参数。因此
引用的参数现在在:eq(…)等中被接受。这一变化
似乎是另一个错误修复的副作用,因为af8206ff..的changelog中没有提到对引用参数的支持,它旨在修复处理jQuery错误12303中的错误:first:last。这个提交是使用git-bisect和一个相对简单的phantomjs脚本发现的。值得注意的是,在e89d06c4..中重写Sizzle之后,Sizzle不仅会对诸如:eq(“3”)之类的选择器无声地失败,它实际上还会引发异常。这应该被视为进一步证明:eq(“3”)支持不是预期行为的证据

关于自定义过滤器,确实有一些基本原理,它们的参数
在某些情况下可能被认为是字符串,有时可能被认为是
选择器,不管它们表面看起来像什么,取决于
评估它们的方法。。。但这一点正在接近
书呆子。只要说没有区别就足够了
至少在调用函数时会使事情变得更简单
不管它们可能表示什么,除了字符串表示

简言之,整个情况可以被视为一种实施
细节,并植根于选择器作为
首先是弦(否则你怎么让它们发出嘶嘶声?)

发表评论