jQuery .has()方法及特定选择器的原生JavaScript等效实现问询
这两个问题问得很到位,咱们逐个来解决:
1. 有没有和jQuery .has()等效的原生JavaScript实现?
原生JS里并没有和jQuery .has()完全一一对应的方法,但现在有两种非常实用的替代方案:
方案一:用CSS :has()伪类(推荐,现代浏览器)
现在主流浏览器(Chrome、Firefox 121+、Safari 15.4+)都已经支持CSS的:has()伪类,它的作用就是筛选包含指定子元素的父元素,用法和jQuery .has()几乎一致。举个例子:
- jQuery写法:
$('.analytics').has('a') - 原生写法:
document.querySelectorAll('.analytics:has(a)')
方案二:手动遍历过滤(兼容旧浏览器)
如果需要兼容一些老旧浏览器,可以先获取目标元素集合,再通过querySelector()检查是否存在子元素来过滤:
// 先拿到所有.analytics元素 const analyticsElements = document.querySelectorAll('.analytics'); // 过滤出包含<a>标签的元素 const filteredElements = Array.from(analyticsElements).filter(el => el.querySelector('a') !== null);
另外也可以用Node.contains()方法,但需要先拿到子元素再反向找父元素,适合特定场景:
const allLinksInAnalytics = document.querySelectorAll('.analytics a'); // 用Set去重,避免同一个.analytics被多次选中 const filteredElements = [...new Set(allLinksInAnalytics.map(link => link.closest('.analytics')))];
2. 目标选择器的原生最优实现
你的需求是:在.main-container内,选取所有id不为"promo"且包含<a>标签的.analytics元素。最优实现分两种情况:
优先推荐:组合使用CSS选择器(简洁高效)
在现代浏览器环境下,直接用:not()和:has()组合的原生选择器就能一步到位,完全匹配你的需求:
const targetElements = document.querySelectorAll('.main-container .analytics:not(#promo):has(a)');
这个选择器的逻辑拆解:
.main-container .analytics:定位到.main-container下所有的.analytics子元素:not(#promo):排除掉id为promo的元素:has(a):只保留内部包含<a>标签的元素
兼容旧浏览器的方案
如果必须支持不兼容:has()的浏览器,可以先拿到初步筛选的元素,再过滤掉不包含<a>的:
// 先获取id不为promo的.analytics元素 const candidateElements = document.querySelectorAll('.main-container .analytics:not(#promo)'); // 过滤出包含<a>标签的元素 const targetElements = Array.from(candidateElements).filter(el => el.querySelector('a') !== null);
这种写法和你已经尝试的代码很接近,只多了一步过滤操作,逻辑清晰,兼容性拉满。
内容的提问来源于stack exchange,提问作者asw1984




