不知道大家在程式設計的時候有沒有遇到過這種情況,就是在迴圈遍歷刪除一部分內容的時候,發現只能刪除其中一部分,而另一部分卻總也刪不掉,然後覺得自己的邏輯沒有問題啊,於是陷入了深深的抑鬱之中……
昨天在處理一段JS指令碼的時候就遇到了這種問題,業務邏輯很簡單,就是獲取HTML某元素下的所有子元素,然後迴圈刪除(其實更簡單的方法是直接innerHTML賦值為空,這裡只是討論一下關於刪除的問題)。我發現每次刪除完,總是有剩餘,也就是刪不乾淨,於是我進行了除錯,發現當有3個元素時刪除完還剩1個,4個元素剩2個……接著就在利用console.log()在瀏覽器進行打樁,無意中發現返回值竟然是list集合!我是利用children屬性來獲取子元素的,程式碼如下:
var city = document.getElementById("city");
var nodes = city.children;
console.log(nodes);
for(var i = 0; i < nodes.length; i++){
city.removeChild(nodes[i]);
}
以前真心沒有注意過,以為children屬性返回的是陣列。由於JS程式碼過於靈活,全都是var型別來接收,而且獲取長度都是通過length,而不是像java中利用size(),確實不好區分。那麼又開始思考一個問題,為什麼list集合就出錯?
我拿一段簡單的java程式碼舉個例子:
List<String> list = newArrayList<String>();
list.add("cc1");
list.add("cc2");
list.add("cc3");
list.add("cc4");
for (inti = 0; i < list.size(); i++) {
list.remove(i);
}
System.out.println(list);
執行結果是:
[cc2, cc4]
沒錯,有兩個元素沒有刪掉!第一反應是list的長度在變化啊,在不斷減小,就像這個例子,第一次i=0,list長度是4,而第二次i=1,list長度就變成了3,所以根本不會比較4次!於是很自然將程式碼進行修改:
int len =list.size();
for (inti = 0; i < len;i++) {
list.remove(i);
}
卻發現數組越界!!!
這說明了一個問題,就是list的下標發生變化了!當經過思考終於明白,其實當你刪除掉list[0]之後,原來的list[1]變成了現在的list[0],原來的list[2]變成了現在的list[1],所以這麼刪除才會下標越界!
那麼不妨利用while迴圈一直刪除第一項:
while(list.size() > 0){
list.remove(0);
}
這樣結果就對了!迴歸到原來的JS程式碼,發現這樣確實可以解決問題!
而且,你還可以倒著刪除!
總結:
其實這原理很簡單,大家都不難理解,關鍵就是怕有時候大家忽略這一點,一時想不到原因,所以才加以總結。
至少,我有了兩點收穫:
JavaScript中也應該時刻關注一下返回值型別,處理陣列和集合的手段還是不一樣的。
迴圈刪除集合元素,還是推薦用while,只要一直刪除第一項或者最後一項即可,就像刪除佇列一樣!而且,你還可以倒著刪除!