歡迎光臨
每天分享高質量文章

javascript 偽陣列實現方法

作者:兩儀的部落格

網址:http://segmentfault.com/a/1190000002998114

點選“閱讀原文”可檢視本文網頁版


什麼是偽陣列

能透過Array.prototype.slice轉換為真正的陣列的帶有length屬性的物件。

這種物件有很多,比較特別的是arguments物件,還有像呼叫getElementsByTagName,document.childNodes之類的,它們都傳回NodeList物件都屬於偽陣列。

我們可以透過Array.prototype.slice.call(fakeArray)將偽陣列轉變為真正的Array物件。

來看個示例:

var fakeArray01 = {0:’a’,1:’b’,length:2};//這是一個標準的偽陣列物件

var arr01 = Array.prototype.slice.call(fakeArray01);

alert(arr01[0]);//a

var arr02 = [].slice.call(fakeArray01);

alert(arr02[0]);//a

slice 可以用來獲取陣列片段,它傳回新陣列,不會修改原陣列。

示例中可以看到fakeArray被成功的轉換成了Array物件。也許大家對Array.prototype.slice.call這種寫法比較陌生,其實我們也可以透過[].slice.call這種形式實現同樣的效果,那為什麼我們要透過prototype的形式實現呢,答案是以prototype的形式執行程式效率更高,同樣程式碼也更加優美。

偽陣列的實現

我們來看一些特殊的用例

var fakeArray01 = {a:’a’,b:’b’,length:2};//沒有length下標對應的值

var arr01 = Array.prototype.slice.call(fakeArray01);

alert(arr01[0]);//undefined

var fakeArray02 = {0:’a’,1:’b’,length:’num’};//length不是數值

var arr02 = Array.prototype.slice.call(fakeArray02);

alert(arr02[1]);//undefined

同樣fakeArray01和fakeArray02被轉換成了真正的陣列,但是陣列中的值都為undefined

檢視 V8 引擎 array.js 的原始碼,可以將 slice 的內部實現簡化為:

function slice(start, end) {

var len = ToUint32(this.length), result = [];

for(var i = start; i < end; i++) {

result.push(this[i]);

}

return result;

}

可以看出,slice 並不需要 this 為 array 型別,只需要有 length 屬性即可。並且 length 屬性可以不為 number 型別,當不能轉換為數值時,ToUnit32(this.length) 傳回 0.

根據以上結論可以得出:fakeArray01被轉換成了lenth為2的陣列,其值都被初始化為undefined,fakeArray02被轉換成了length為0的陣列,自然訪問下標為1的元素傳回undefined

IE的問題

針對於標準瀏覽器slice實現已經可以解釋所有的問題,但是IE在處理NodeList時出現了問題。IE中無法將NodeList轉換為真正的陣列,會出錯。這又是為什麼呢?嚴格說,在IE內部定義了一個抽象類Arraioid,Array和Arguments都繼承與此,所以可以用slice。但DOM物件是透過COM接入到JScript的,slice檢測的時候失效。

Jquery與偽陣列

Jquery內部大量運用了偽陣列。可以說整個Jquery物件,都是構建在偽陣列的基礎之上的,好讓我們來看一些Jquery的實際運用:

fakeArray

贊(0)

分享創造快樂