jQuery使用parents().filter匹配data-floor为0的父元素失效的原因
问题产生核心原因
这个现象是jQuery的data()方法特性结合JS的假值判断逻辑共同导致的,根本不是选择器本身的bug:
- 首先jQuery的
data()方法读取DOM上的data-*属性时,会自动做类型推断:如果属性值转成数字后,转回字符串和原字符串完全一致,就会把值转成对应的Number类型。比如data-floor="0"读出来是数字0;而data-floor="00"转数字后是0,转回字符串是"0",和原字符串"00"对不上,因此会保留原字符串"00",不会做数字转换。 - 其次jQuery的
filter()方法判断元素是否匹配时,会把回调的返回值转成布尔值,只要是假值(比如数字0、空字符串、null),就会把对应元素从匹配集合里剔除。 - 碰到这个问题的典型写法,是在filter回调里直接写
return $(this).data("floor"),想靠返回值的真假代表元素“有没有data-floor属性”:当属性值为"0"时,读出来的数字0是假值,就会被filter误判为不匹配,直接排除;当属性值为"00"时,读出来的字符串"00"是真值,就能被正常保留,和实际观察到的现象完全对上。
可落地的修正方案
- 不要靠data返回值的真假判断属性存在性:筛选带特定data属性的元素时,要显式判断属性是否真实存在,别把data值当真假判断依据,比如:
// 显式判断属性存在的正确写法 return $(this).is("[data-floor]"); // 直接读原生DOM属性判断,还能绕开data的类型转换逻辑 return this.hasAttribute("data-floor"); - 如果需要匹配特定的data属性值,要做显式等值判断:哪怕目标值是数字0,只要写清楚对比规则,就不会被假值逻辑误判,比如:
var targetFloor = 0; // 显式等值判断,不会因为0是假值就被错误排除 return $(this).data("floor") === targetFloor; - 补充提示:如果是直接用jQuery内置的属性选择器做筛选(比如
parents("[data-floor]")),是不会触发这个问题的——这类选择器的判断逻辑基于DOM原生属性的存在性,和data()的类型推断逻辑无关,哪怕属性值是"0"也能正常匹配。
内容的提问来源于stack exchange,提问作者Dan Terkildsen
相关产品推荐
相关产品推荐

