多个后代选择器,错误还是误解?

Mic*_*ipp 5 javascript css queryselector

以下两种选择节点的方法不应该产生相同的结果吗?

let tmp = fruits.querySelector("ul:first-of-type li:first-of-type");
tmp = tmp.querySelector("span")    
Run Code Online (Sandbox Code Playgroud)

对比

let tmp = fruits.querySelector("ul:first-of-type li:first-of-type span");
Run Code Online (Sandbox Code Playgroud)

(在此处查看实际操作)

我已经在 Firefox 和 chrome 中对此进行了测试。两种情况下的结果不同。任何人都可以请解释为什么?

堆栈片段中的示例:

let tmp = fruits.querySelector("ul:first-of-type li:first-of-type");
tmp = tmp.querySelector("span")    
Run Code Online (Sandbox Code Playgroud)
let tmp = fruits.querySelector("ul:first-of-type li:first-of-type span");
Run Code Online (Sandbox Code Playgroud)

Seb*_*mon 2

文档对此进行解释:

\n
\n
element = baseElement.querySelector(selectors);\n
Run Code Online (Sandbox Code Playgroud)\n

返回值

\n

其第一个后代元素baseElement与指定的 组匹配selectors匹配时会考虑元素的整个层次结构,包括元素集之外的元素(包括baseElement及其后代);换句话说,selectors首先应用于整个文档,而不是baseElement, 以生成潜在元素的初始列表。然后检查生成的元素以查看它们是否是 的后代baseElement。剩余元素的第一个匹配项由querySelector

\n
\n

(强调我的。)

\n

让\xe2\x80\x99s考虑一个简化的例子:

\n

\r\n
\r\n
console.log(document.getElementById("a").querySelector("ul li span"));
Run Code Online (Sandbox Code Playgroud)\r\n
<ul>\n  <li id="a"><span>A</span>\n    <ul>\n      <li><span>B</span></li>\n    </ul>\n  </li>\n</ul>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

baseElementdocument.getElementById("a"); selectors"ul li span"

\n

document.querySelector("ul li span")确实包括两个<span>s,并且它们都在 内部baseElement<span>A</span>恰好是这组中的第一个。

\n

有\xe2\x80\x99s一个相当新的伪类,称为:scope,可能会在这里有所帮助:

\n

\r\n
\r\n
console.log(document.getElementById("a").querySelector(":scope ul li span"));
Run Code Online (Sandbox Code Playgroud)\r\n
<ul>\n  <li id="a"><span>A</span>\n    <ul>\n      <li><span>B</span></li>\n    </ul>\n  </li>\n</ul>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n