Javascript技巧之不要用for in語句對數組進行遍曆

來源:互聯網
上載者:User

一,為什麼不要用for in語句

jqModal這個jquery外掛程式估計很多人都使用過,在jqModal源碼內部,有一個函數為hs,其中有個嵌套迴圈如下, 複製代碼 代碼如下:for(var i in {jqmShow:1,jqmHide:1})
for(var s in this[i])
if(H[this[i][s]])
H[this[i][s]].w[i](this);
return F;
}

第一個for in遍曆的目標是個匿名對象,沒有問題。
第二個for in遍曆,根據上下文確認this[i]是一個數組對象(Array)。
很多JS先驅者都告誡過我們不要對數組對象使用for in語句進行遍曆,原因除了效能外,還有可能產生意料之內的bug。不聽先人言,吃虧在眼前呵呵。
今天偶拿jqModal為例,說明下這種bug到底什麼時候會出現,當引以為戒。
二,問題重現
關鍵詞:原生Array類、擴充Array類
for in 語句對數組對象進行遍曆潛在的bug在於:如果原生Array類被其他的js指令碼庫進行了原型擴充(比如多加一個toJSON方法即Array.prototype.toJSON=xxxx),那麼用for in遍曆擴充後的Array對象的邏輯將與遍曆原生Array對象的邏輯發生差異。
舉個簡單的例子,

複製代碼 代碼如下:var x=[1];
for(var s in x){
alert(s);
};

按常理,如果Array是原生js類,上面語句應該只執行一次alert方法,且s為數組的索引0。但是,如果Array類被擴充了,多了一個toJSON方法,那麼上面的語句將執行兩次alert,第一次s為索引0,第二次s為方法名'toJSON'。

如果你設計的代碼的邏輯以原生Array類為基準,在某一天你的同事在頁面裡面引用了一個第三方的JS庫,這個庫又恰好擴充了Array類,結果將難以想象,很有可能原來的代碼邏輯將不再成立。

關於這種擴充原生JS類的庫,很有名的一個就是prototype.js,它給Array類擴充了很多方法諸如toJSON,each等等。我現在明白為啥jquery的創始人曾經對prototype火大了(不少人因為特殊原因在一個頁面裡用jquery同時又用prototype,會有很多意料之外的衝突問題,僅僅一個noConflict是無法解決的)。另外,jqModal的作者如果看得懂我這篇文章估計也會對埋怨prototype,說:“我用for in對數組遍曆是不明智的,但是更該死的還是prototype。。。”

如上所述,如果你在用jqModal,同時因為別的原因在用prototype,恭喜你中招了。衝突將導致jqModal的彈框在ie6、ie7下面將無法利用closeClass設定的按鈕進行自動關閉。跟蹤調試代碼你將發現,異常的地方就在本文開頭提到的hs方法的for in 迴圈中。。。
三,解決問題
遍曆數組的地方,用for var 語句代替for in。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.