數組的
map
方法在IE9如下是不支持的,所以須要寫一個兼容方法來實現此行爲,在實現兼容的時候:必須注意:對於數組中被刪除(delete
)或者根本從未賦值的索引項,map
中第一個函數參數是不會執行的。javascript
關於這一點,在ECMA標準和MDN參考文檔都是有說明的:html
MDN:
it is not invoked for indexes that are undefined, those which have been deleted or which have never been assigned values.java
ECMA:
callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.數組
我看到一些用來兼容的方法,都沒有注意到這種情形,那麼不注意這種情形會出現什麼問題呢?爲何MDN上給的兼容方法會這麼曲折呢?瀏覽器
我先把我在培訓班的老師給出的兼容方法貼出來:app
javascriptArray.prototype.myMap = function (fn, context) { context = context || window; var ary = []; if (Array.prototype.map) { ary = this.map(fn, context); } else { for (var i = 0; i < this.length; i++) { ary[i] = fn.apply(context, [this[i], i, this]); } } return ary; }
這個實現比較簡單,流程很清晰,若是瀏覽器有原生數組map
方法,調用該方法,不然執行else
中的語句;可是若是是下面這樣一個數組,在沒有實現原生map
方法的瀏覽器中,結果跟原生map方法調用不同:函數
javascriptvar arr=[1,2,,,3]; console.dir(arr.myMap(function(e,i,a){return e*2;}));
原生map方法執行上述代碼的輸出是
this
而若是瀏覽器不支持原生map方法,會執行else語句,這樣的輸出是:
spa
你看,這二者執行區別就在於一開始的結論:原生的map
方法跳過了那些從未賦值的索引對應的項。prototype
簡單來講,對象就是一系列屬性名值對,即某個屬性名對應某個屬性值;當咱們遍歷對象時,不在對象中的屬性固然不會被訪問到。
而在JS中,數組就是對象,甚至數組的一些遍歷方法,在內部執行的時候,都是先將數組轉化爲對象,
javascriptvar O=Object(this);
而後遍歷數組對象中,全部已經定義的,且索引爲數字的項。在絕大部分狀況下,這些數字恰好是連續的。那何時會出現不連續呢?我所知道有這兩種;
以字面量方式新建立數組的時候,連續的逗號,會造成數字索引不連續;如var arr=[1,2,,,3]
,你能夠在瀏覽器控制檯中試試輸出console.dir([1,2,,,3])
的結果(注意,必定要用console.dir
方法);
利用delete
操做符刪除數組中的某項。咱們知道delete
操做符用於刪除對象中某個屬性,而JS中,數組就是對象的一種,數組的索引就是其屬性名,對應的項就是屬性值。用delete
刪除後,數組中的這對屬性名值對(又稱鍵值對)就不存在了,這時候對其採用遍歷方法,固然不會針對不存在名值對進行調用了。
undefined
的項,儘管若是強行訪問,結果都是undefined
,可是是不太同樣的,好比這樣一個數組,[1,,undefined];
,該數組(如今咱們能夠更準確得說:數組對象)中不存在索引爲1的項,可是卻存在索引爲2的項,能夠用console.dir
輸出看出區別。說到上面這些,你確定已經意識到了,既然數組的索引能夠被跳過,那數組的length屬性還能反映其長度嗎?
關於這個問題,我是這麼理解的,
數組的length屬性並不能反應數組中元素的數目,在絕大多數狀況(即沒有人工干預length
屬性,且數組中沒有跳過的索引),它只是恰好,恰好等於最大的索引加一。當咱們從對象的角度來看待數組時,像0、一、二、三、四、五、6等等這些數字索引和length
同樣,都只是數組對象的屬性。
用delete
操做符刪除數組任意一項,或者將任意一項值賦值爲undefined
,length
不改變;
當人爲地設置數組的length
屬性值時,length
隨之改變,同時索引不小於該值的都會被從數組中完全刪除。