一、發現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, 如君真要使用,請慎重。
本文為作者原創,轉載請注明出處,與你分享我的快樂
http://www.cnblogs.com/weirhp