一、发现bug的过程
今天同事在使用我做的js表单验证控件时,发现当表单中存在一个name为nodeType的input时,验证组件就不好用了。经简单测试发现$('form :input')根本选择不到一个元素,心想这肯定是jquery的bug了。
二、分析bug
然后就打开jquery的源码粗略看了一下,发现里里边好多好多的代码都关系着nodeType的属性,这让我如何下手呢?这可是将近一万行的代码。泪奔呀。。。
随便打几个断点试试吧,无效无效。。。。心中那个纠结那个郁闷。。。
无意间发现了代码里这样一行注释。
/*!* Sizzle CSS Selector Engine v1.9.4-pre* http://sizzlejs.com/** Copyright 2013 jQuery Foundation, Inc. and other contributors* Released under the MIT license* http://jquery.org/license** Date: 2013-05-27*/
心想我的这个问题肯定就是css选择器的问题,从这里下手肯定是对的。
然后去这个地址下载了sizzle.js,发现这个选择器问题在这里也是存在的。心中窃喜。然后就一点点调试找到了问题的根源。
发现的问题是什么呢?
就是当form表单里如果有一个 nodeType这样的一个input时,$('form')[0].nodeType 不等于1了,他的值是这个input对象。
三、解决bug
最后修改代码
把
if ( elem.nodeType === 1 || checkNonElements ) {
修改为
if ( (elem.nodeType === 1 || typeof elem.nodeType != "number") || checkNonElements ) {
(共有三处)
修改后发现Sizzle('form :input')好用了,对应地修改jquery里的 ,$('form :input')好用了。
但是悲催的是我的验证控件还是不好用。测试发现是因为$('form').find(':input')不好用造成的。心想难道还必须调试jquery的源码吗?心灰意冷了。真的想放弃了。刚才的喜悦与成就感没了。。。。。。
上网上又随便地查一些资料,查一些别人对jquery源码的剖析等,发现问题肯定还是出在Sizzle里,并悟出了find的方法应该就是Sizzle(':input',Sizzle( 'form ')[0]) ,测试发现我修改后的代码使用这种表达式依然不好用。(Sizzle中没有find的方法)
然后基于这个表达式进行测试,修改了另一处代码:
把
if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
替换为:
if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 && (typeof context.nodeType === "number")) {
大功告成。
以上修改方案仅为个人修改意见,并不能保证不会引发其它bug, 如君真要使用,请慎重。
本文为作者原创,转载请注明出处,与你分享我的快乐