JavaScript中「數組也是對象」

先說結論吧:

數組的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);

而後遍歷數組對象中,全部已經定義的,且索引爲數字的項。在絕大部分狀況下,這些數字恰好是連續的。那何時會出現不連續呢?我所知道有這兩種;

  1. 以字面量方式新建立數組的時候,連續的逗號,會造成數字索引不連續;如var arr=[1,2,,,3],你能夠在瀏覽器控制檯中試試輸出console.dir([1,2,,,3])的結果(注意,必定要用console.dir方法);

  2. 利用delete操做符刪除數組中的某項。咱們知道delete操做符用於刪除對象中某個屬性,而JS中,數組就是對象的一種,數組的索引就是其屬性名,對應的項就是屬性值。用delete刪除後,數組中的這對屬性名值對(又稱鍵值對)就不存在了,這時候對其採用遍歷方法,固然不會針對不存在名值對進行調用了。

有一點要特別注意,數組中被刪除的項或者從未定義的項,與人爲將其值設置爲undefined的項,儘管若是強行訪問,結果都是undefined,可是是不太同樣的,好比這樣一個數組,[1,,undefined];,該數組(如今咱們能夠更準確得說:數組對象)中不存在索引爲1的項,可是卻存在索引爲2的項,能夠用console.dir輸出看出區別。

數組的length屬性還能反映數組長度嗎?

說到上面這些,你確定已經意識到了,既然數組的索引能夠被跳過,那數組的length屬性還能反映其長度嗎?

關於這個問題,我是這麼理解的,

  1. 數組的length屬性並不能反應數組中元素的數目,在絕大多數狀況(即沒有人工干預length屬性,且數組中沒有跳過的索引),它只是恰好,恰好等於最大的索引加一。當咱們從對象的角度來看待數組時,像0、一、二、三、四、五、6等等這些數字索引和length同樣,都只是數組對象的屬性。

  2. delete操做符刪除數組任意一項,或者將任意一項值賦值爲undefinedlength不改變;

  3. 當人爲地設置數組的length屬性值時,length隨之改變,同時索引不小於該值的都會被從數組中完全刪除。

相關文章
相關標籤/搜索