读jQuery源码的人大概都见过这样一个定义:var rcheckableType = ( /^(?:checkbox|radio)$/i );。短短一行正则,却在jQuery内部的多个模块里反复出现。它存在的意义只有一个:把checkbox和radio这两类可勾选元素从所有input中识别出来,走一套与普通input不同的处理分支。很多前端开发者遇到的checkbox取值异常、serializeArray漏掉字段、attr设置checked失效等问题,根源都能追到这段逻辑上。本文把这个正则相关的所有调用点梳理一遍,把jQuery对可勾选元素的特殊处理讲透。

一、rcheckableType正则本身的定义与设计细节
先看正则原文:/^(?:checkbox|radio)$/i。结构非常简单,锚定字符串开头和结尾,中间用非捕获分组匹配checkbox或radio这两个单词,最后加i标志做大小写不敏感匹配。之所以要加大小写容忍,是因为HTML规范里type属性值不区分大小写,浏览器解析时会把type="CHECKBOX"和type="checkbox"视为同一类型,但elem.type返回的是原始字符串。如果jQuery只做严格小写匹配,遇到大写写法的DOM就会漏判。
这个正则的判断对象永远是elem.type,也就是元素节点上的type属性值,而不是nodeName。这意味着它只对input元素有意义。jQuery在内部调用它之前,通常已经先判断过elem.nodeName.toLowerCase() === "input",二者配合构成完整的识别条件。用正则而非字符串相等判断的好处是集中管理:如果将来需要扩展,比如把某种新的可勾选类型纳入,只需要改这一处正则,所有依赖它的模块自动生效。
还要注意一点,这个正则用的是.test()方法配合变量缓存结果,例如在buildFragment或序列化流程里会看到类似!rcheckableType.test(elem.type)的写法。test返回布尔值,配合逻辑非,语义就是“这不是一个可勾选元素”,这种反向判断在源码里出现频率很高,读的时候容易绕晕,建议对照上下文把语义翻正过来再理解。
二、clone场景下的特殊处理:checked状态如何被复制
rcheckableType最早被大量讨论的调用点在jQuery.clone相关逻辑里。DOM原生的cloneNode方法在克隆元素时,不会复制用户在页面上实时勾选产生的checked状态——原生克隆只复制特性节点(attribute),而用户点击修改的是属性(property)。对文本框来说这个问题不存在,因为value特性的初值会照常复制;但对checkbox和radio来说,用户勾没勾这个状态完全丢失。
jQuery的做法是在克隆函数中判断元素是否匹配rcheckableType,匹配则额外把src.checked这个property同步到克隆节点上。相关逻辑简化后大致如下:
// jQuery源码中clone的简化逻辑
function fixCloneNodeIssues( src, dest ) {
var nodeName = dest.nodeName.toLowerCase();
// 只对input元素做勾选状态同步
if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
// 关键:把用户交互产生的checked属性(property)复制过去
dest.checked = src.checked;
// value的property也可能被脚本改过,同样需要同步
if ( dest.value !== src.value ) {
dest.value = src.value;
}
}
}
这段代码体现了attribute和property的核心区别:dest.defaultChecked在cloneNode时已经复制了,但dest.checked不会。jQuery用rcheckableType圈定出需要这种补丁的元素范围,避免了给所有元素都加无意义的赋值操作。如果没有这个正则做门卫,克隆一批复选框后所有勾选状态归零,表单回显功能会直接崩掉。
三、val取值与attr/prop的区分:为什么checkbox的value不等于它的状态
第二个重要调用点在jQuery.fn.val和jQuery.fn.attr的钩子体系里。checkbox和radio的value特性只表示“被勾选时提交给服务器的值”,和当前是否勾选是两回事。很多初学者用$("#cb").val("xxx")想让复选框被选中,结果只是改了提交值,勾选状态纹丝不动,这就是没理解这对概念的表现。
jQuery在attr模块里对checked做了明确限制。当设置attr值为false时,对于匹配rcheckableType的元素,jQuery会移除checked特性并强制把property设为false;设置为true时则设置特性。这个分支判断的入口正是这个正则。简化逻辑如下:
// attr钩子中对checked的处理(简化)
attrHooks: {
type: function( elem, value ) {
if ( !support.radioValue && value === "radio" &&
nodeName( elem, "input" ) ) {
var val = elem.value;
elem.setAttribute( "type", value );
if ( val ) {
elem.value = val;
}
return value;
}
}
}
上面这段其实是type钩子,处理的是另一个经典坑:老版本IE中修改input的type会清空value。而针对checked的prop处理中,jQuery.fn.prop内部对boolean类型的property有专门映射,rcheckableType匹配的元素在设置checked时会同时维护特性与属性的同步关系。理解这条链路后就能解释:为什么$el.prop("checked", true)能正常勾选,而$el.attr("checked", "checked")在某些版本里行为诡异——特性只代表初始默认值,属性才代表实时状态。
四、serializeArray序列化:为什么没勾选的checkbox消失了
第三个调用点在表单序列化。jQuery的.serializeArray()和.serialize()在收集字段时有一条过滤规则:checkbox和radio只有处于checked状态才参与序列化,其他input只要name存在就会参与。这条规则的实现依赖rcheckableType。核心代码简化如下:
function serialize( elements ) {
var i, l, element, value;
for ( i = 0, l = elements.length; i < l; i++ ) {
element = elements[ i ];
if ( element.name && !element.disabled &&
rsubmittable.test( element.nodeName ) ) {
// 可勾选元素必须checked才收集,其余元素直接收集
if ( !rcheckableType.test( element.type ) || element.checked ) {
value = jQuery( element ).val();
if ( value != null ) {
result.push( { name: element.name, value: value } );
}
}
}
}
}
注意那行关键判断:!rcheckableType.test( element.type ) || element.checked。翻译成人话就是:如果你不是checkbox或radio,无条件通过;如果你是,必须checked为true才通过。这就是为什么后端有时候收不到某个checkbox字段——不是序列化出了bug,而是用户根本没勾选。如果你有“即使未勾选也要传一个空值”的业务需求,就不能直接用serializeArray,需要手动遍历补充。
顺带一提,radio的互斥特性也让这段逻辑变得必要。一组同name的radio只会有一个checked,序列化时自然只输出被选中那一项的value。jQuery没有对radio做额外分组处理,靠的完全是DOM本身的互斥行为加这个统一的过滤条件,实现相当克制。
五、从rcheckableType看jQuery的设计取舍
回头看,这个正则的价值在于用最小的代价圈定一类行为特殊的元素。checkbox和radio的特殊性本质上来自HTML表单模型:它们的用户交互状态(checked)和提交值(value)是分离的,而且提交行为是条件性的。原生DOM API对这种分离的支持很粗糙,cloneNode丢状态、attr与prop混淆等问题都要开发者自己踩坑。jQuery选择在clone、attr/prop、序列化这三个最痛的点上,用同一个正则做统一的元素识别,然后各打一个补丁。
这种设计对日常开发的启示是:凡是操作可勾选元素,先想清楚你要动的是状态还是值。要判断勾选用.is(":checked")或.prop("checked"),要改勾选用.prop("checked", bool),要拿提交值用.val(),要用attr去碰checked基本都会出问题。把这几个方法的选择和rcheckableType背后的attr/prop分离模型对应起来,checkbox相关的疑难杂症基本都能自己定位。现代框架虽然已经淡化了这些细节,但理解jQuery这层封装的历史逻辑,对掌握浏览器表单机制本身依然有直接帮助。
jQuery源码rcheckableTyperadio checkbox修改时间:2026-09-08 07:26:58