作者:slife的部落格
網址:http://segmentfault.com/a/1190000002995303
點選“閱讀原文”可檢視本文網頁版
先說結論吧:
陣列的map方法在IE9以下是不支援的,因此需要寫一個相容方法來實現此行為,在實現相容的時候:必須註意:對於陣列中被刪除(delete)或者根本從未賦值的索引項,map中第一個函式引數是不會執行的。
關於這一點,在ECMA標準和MDN參考檔案都是有說明的:
MDN:
it is not invoked for indexes that are undefined, those which have been deleted or which have never been assigned values.
ECMA:
callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.
我看到一些用來相容的方法,都沒有註意到這種情形,那麼不註意這種情形會出現什麼問題呢?為什麼MDN上給的相容方法會這麼曲折呢?
我先把我在培訓班的老師給出的相容方法貼出來:
Array.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方法呼叫不一樣:
var arr=[1,2,,,3];
console.dir(arr.myMap(function(e,i,a){return e*2;}));
原生map方法執行上述程式碼的輸出是
而如果瀏覽器不支援原生map方法,會執行else陳述句,這樣的輸出是:
你看,這兩者執行區別就在於一開始的結論:原生的map方法跳過了那些從未賦值的索引對應的項。
陣列也是物件!!
簡單來說,物件就是一系列屬性名值對,即某個屬性名對應某個屬性值;當我們遍歷物件時,不在物件中的屬性當然不會被訪問到。
而在JS中,陣列就是物件,甚至陣列的一些遍歷方法,在內部執行的時候,都是先將陣列轉化為物件,
var 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屬性並不能反應陣列中元素的數目,在絕大多數情況(即沒有人工幹預length屬性,且陣列中沒有跳過的索引),它只是剛好,剛好等於最大的索引加一。當我們從物件的角度來看待陣列時,像0、1、2、3、4、5、6等等這些數字索引和length一樣,都只是陣列物件的屬性。
- 用delete運運算元刪除陣列任意一項,或者將任意一項值賦值為undefined,length不改變;
- 當人為地設定陣列的length屬性值時,length隨之改變,同時索引不小於該值的都會被從陣列中徹底刪除。