Element.matches()用于判断元素是否匹配CSS选择器,返回布尔值,Chrome34+等现代浏览器支持,IE不支持需polyfill;必须在元素实例上调用,不支持伪元素,事件委托中宜配合closest()使用。

Element.matches() 的基本用法和兼容性确认
Element.matches() 是原生 DOM 方法,用于判断当前元素是否匹配给定的 CSS 选择器字符串。它返回布尔值,不触发重排或重绘,性能安全。
- 浏览器支持良好:Chrome 34+、Firefox 34+、Safari 7+、Edge 12+,IE 完全不支持(需用
matchesSelector旧名或 polyfill) - 注意不是静态方法,必须调用在具体元素实例上,比如
div.matches('.btn.active'),不能写Element.matches(...) - 选择器必须是合法的 CSS 选择器,不支持伪元素(如
::before),但支持大部分伪类(:hover除外——运行时无意义,但语法上不会报错)
常见错误现象:document.querySelector('input').matches(':invalid') 返回 false 即使输入框当前确实无效——因为 :invalid 是表单有效性伪类,匹配结果取决于元素当前状态,而该方法只做静态语法匹配(实际会按规范求值,但依赖浏览器实现一致性;建议优先用 checkValidity() 配合 JS 判断)
如何安全处理 IE 和旧版浏览器
IE9–11 支持的是带前缀的旧方法名,需手动 fallback:
- IE9–10:使用
msMatchesSelector - IE11:支持
matches,但早期版本可能仍需msMatchesSelector - 不建议自行检测 UA,应采用特性检测
function elementMatches(el, selector) {
return el.matches
? el.matches(selector)
: el.msMatchesSelector
? el.msMatchesSelector(selector)
: false;
}- 不要用
typeof el.matches === 'function'判定,IE11 在某些文档模式下可能暴露matches但行为异常 - 如果项目已引入
core-js或babel-polyfill,确认其是否覆盖了Element.prototype.matches(新版 core-js 默认包含)
matches 在事件委托中的典型误用
很多人想用 matches 替代 closest() 做事件代理,但逻辑容易出错:
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
if (e.target.matches('.list-item')) { ... }—— 这只匹配目标自身,忽略子元素(比如点击了.list-item span,e.target是span,不匹配) - 正确思路:先用
e.target.closest('.list-item')获取最近匹配祖先,再判断是否非 null;或者用matches时主动向上遍历(不推荐,冗余)
更稳妥的事件委托结构:
list.addEventListener('click', e => {
const item = e.target.closest('.list-item');
if (!item) return;
// 此时 item 是匹配的 .list-item 元素,可安全操作
});-
closest()内部也基于matches实现,但封装了祖先遍历逻辑,语义更清晰 - 若坚持用
matches,必须配合循环parentNode,且注意Document和ShadowRoot边界(matches对 shadow host 无效)
选择器字符串的边界情况和调试技巧
matches 对选择器格式敏感,以下情况易被忽略:
- 空格影响语义:
el.matches('div .content')是后代选择器,匹配div内任意层级的.content;而el.matches('div.content')是类名复合,要求元素同时是div且有content类 - 属性选择器需严格匹配值:
el.matches('[data-id="123"]')中的"123"必须与元素实际data-id属性值完全一致(包括引号类型无关,但内容必须相同) - 使用变量拼接时注意空格和转义:
el.matches(<code>[data-type="${type}"]) 中若type含空格或特殊字符(如user name),会导致语法错误;应改用JSON.stringify或正则清洗
调试建议:把选择器复制到浏览器控制台,执行 document.querySelector(selector) 看是否能取到元素,再比对 el.matches(selector) 结果——两者语义不同,但能快速验证选择器本身是否合法
真正容易被忽略的是:匹配发生在当前 DOM 状态快照,不响应动态 class 切换或属性变更后的异步延迟;如果刚用 el.classList.add('active') 就立刻 el.matches('.active'),结果一定为 true,但若该操作被包裹在 requestAnimationFrame 或 setTimeout 中,则需确保调用时机。



















