当多个元素具有相同的“id”时,jQuery如何工作?

我从Google的AdWords网站获取具有相同id多个元素的数据。

你能解释为什么以下三个查询不会导致相同的答案(2)?

现场演示

HTML:

 <div> <span id="a">1</span> <span id="a">2</span> <span>3</span> </div> 

JS:

 $(function() { var w = $("div"); console.log($("#a").length); // 1 - Why? console.log($("body #a").length); // 2 console.log($("#a", w).length); // 2 }); 

根据W3C规范,具有相同ID的2个元素不是有效的html。

当您的CSSselect器只有一个IDselect器(并且不在特定上下文中使用)时,jQuery使用本地document.getElementById方法,该方法仅返回具有该ID的第一个元素。

然而,在另外两个实例中,jQuery依赖于Sizzleselect器引擎(或者querySelectorAll ,如果可用的话),这显然select了这两个元素。 结果可能会因浏览器而异。

但是,您不应该在同一个页面上拥有两个具有相同ID的元素。 如果你需要为你的CSS,请使用类。


如果您绝对必须通过重复ID进行select,请使用属性select器:

 $('[id="a"]'); 

看看小提琴: http : //jsfiddle.net/P2j3f/2/

注意:如果可能的话,您应该使用标签select器限定select器,如下所示:

 $('span[id="a"]'); 

应该只有一个具有给定ID的元素。 如果您遇到这种情况,请参阅我的答案的后半部分。

具有相同标识的多个元素(非法HTML)时,浏览器的行为如何不由规范定义。 你可以testing所有的浏览器,找出它们的行为,但是使用这个configuration或者依赖任何特定的行为是不明智的。

如果您希望多个对象具有相同的标识符,请使用类。

 <div> <span class="a">1</span> <span class="a">2</span> <span>3</span> </div> $(function() { var w = $("div"); console.log($(".a").length); // 2 console.log($("body .a").length); // 2 console.log($(".a", w).length); // 2 }); 

如果您想要可靠地查看由于无法修复文档而具有相同ID的元素,则必须执行自己的迭代,因为您不能依赖任何内置的DOM函数。

你可以这样做:

 function findMultiID(id) { var results = []; var children = $("div").get(0).children; for (var i = 0; i < children.length; i++) { if (children[i].id == id) { results.push(children[i]); } } return(results); } 

或者,使用jQuery:

 $("div *").filter(function() {return(this.id == "a");}); 

jQuery的工作示例: http : //jsfiddle.net/jfriend00/XY2tX/ 。

至于为什么你得到不同的结果,这将与执行实际select器操作的任何代码的内部实现有关。 在jQuery中,你可以研究代码来找出任何给定的版本正在做什么,但是由于这是非法的HTML,所以不能保证它会随着时间的推移保持不变。 从我在jQuery中看到的,它首先检查select器是否像#a这样的简单id,如果是这样,就使用document.getElementById("a") 。 如果select器比这个更复杂,并且querySelectorAll()存在,那么jQuery通常会将select器closures到内置的浏览器函数中,该函数将具有特定于该浏览器的实现。 如果querySelectorAll()不存在,那么它将使用Sizzleselect器引擎来手动查找将自己实现的select器。 因此,根据确切的select器以及浏览器的新增function,您可以在同一浏览器系列中至less有三种不同的实现。 然后,各个浏览器都将拥有自己的querySelectorAll()实现。 如果您想要可靠地处理这种情况,您可能必须使用您自己的迭代代码,如上所述。

jQuery的idselect器只返回一个结果。 第二个和第三个语句中的descendantmultipleselect器被devise为select多个元素。 它类似于:

声明1

 var length = document.getElementById('a').length; 

…产生一个结果。

声明2

 var length = 0; for (i=0; i<document.body.childNodes.length; i++) { if (document.body.childNodes.item(i).id == 'a') { length++; } } 

…产生两个结果。

声明3

 var length = document.getElementById('a').length + document.getElementsByTagName('div').length; 

…还产生两个结果。

从IDselect器jQuery页面 :

每个id值只能在文档中使用一次。 如果多个元素被分配了相同的ID,则使用该ID的查询将仅selectDOM中的第一个匹配元素。 不过,这种行为不应该依赖。 具有多个使用相同ID的元素的文档是无效的。

顽皮的谷歌。 但他们甚至不closures我听到的<html><body>标签。 问题是,为什么Misha的第二和第三个查询返回2而不是1。

如果您有多个具有相同ID或相同名称的元素,只需将相同的类分配给这些多个元素,并通过索引访问它们并执行您所需的操作。

  <div> <span id="a" class="demo">1</span> <span id="a" class="demo">2</span> <span>3</span> </div> 

JQ:

 $($(".demo")[0]).val("First span"); $($(".demo")[1]).val("Second span"); 

你可以直接写$('span#a')。length来获得长度。

这是你的代码的解决scheme:

 console.log($('span#a').length); 

尝试JSfiddle: https ://jsfiddle.net/vickyfor2007/wcc0ab5g/2/