自己給JS陣列新增更多疊代器(具有疊代功能的方法)

2020-07-16 10:05:02
JavaScript 為陣列定義了多個具有疊代功能的方法,如 forEach、filter、map、every、some。本節練習使用 JavaScript 設計自己的疊代器。

疊代器(Iterator)提供了一種對資料集合中每個元素執行重複操作的機制,通常與迴圈結構配合使用,因此也稱為迴圈器。它能夠根據傳遞的函數型引數為集合中每個元素反復執行相同的命令,直到滿足某些條件為止。疊代器通常用於迭代陣列的值,或者執行重複的任務。

實現程式碼

Array.prototype.each = function (f) {  //陣列疊代器,擴充套件Array原型反復
    try{  //例外處理,避免不可預測的錯誤
        this.i || (this.i = 0);  //初始化迭代計數器
        if (this.length > 0 && f.constructor == Function) {  //如果陣列長度大於0,引數為函數
            while (this.i < this.length) {  //遍歷陣列
                var e = this[this.i];  //獲取當前元素
                if (e && e.constructor == Array) {  //如果元素存在,切為陣列
                    e.each(f);  //遞回呼叫疊代器
                } else {  //否則,在元素上呼叫引數函數,並傳遞值
                    f.apply(e, [e]);
                }
                this.i ++;  //遞加計數器
            }
            this.i = null;  //如果遍歷完畢,則清空計數器
        }
    }catch(w) {  //捕獲異常,暫不處理
        return this;  //返回當前陣列
    }
}

應用程式碼

var a = [1, [2, [3,4]]];
var f = function (x) {
    console.log(x);
}
a.each(f);  //呼叫疊代器,為每個元素執行一次函數傳遞
不能使用 for/in 語句進行迴圈操作,因為 for/in 能夠疊代本地屬性。

範例1

動態改變陣列中每個元素的值。
Array.prototype._edit = Array.prototype.edit || (Array.prototype.edit = function () {  //陣列元素批次處理方法
    var b = arguments, a = [];  //獲取引數,並定義一個臨時陣列
    this.each (function () {  //呼叫疊代器,遍歷所有元素
        a.push(b[0].call(b[1], this));  //呼叫引數函數,把當前元素作為引數傳入
    });
    return a;  //返回臨時陣列
});
Object.prototype.edit = Array.prototype._edit;

設計思路

為 Array 物件定義了一個原型方法 edit(),該方法能夠根據引數函數編輯陣列中每個元素,並返回這個編輯後的陣列。

在這個原型方法中,首先定義臨時變數獲取 edit() 方法的引數,並定義一個臨時陣列,用來儲存編輯後的陣列元素值。然後呼叫疊代器 each(),遍歷陣列中所有元素,為疊代器傳遞一個引數,該函數將在每個元素上執行。在該函數中包含一句處理語句,它通過 call() 方法呼叫傳遞給 edit() 的引數函數,並把當前元素作為引數傳遞給該引數函數進行執行,執行結果被推進臨時陣列 a 中,最後返回這個臨時的陣列 a。
var a = [1,2,3,4];  //定義陣列直接量
var f = function (x) {  //求平方值
    return x * x;
}
var b = a.edit(f);  //為陣列元素執行求平方操作
console.log(b);  //返回[1,4,9,16]
在處理多維陣列時,該原型方法會把它們全部轉換為一維陣列。

範例2

過濾陣列元素。
Array.prototype._filter = Array.prototype.filter || (Array.prototype.filter = function () {
    var b = arguments, a = [];
    this.each(function () {
        if (b[0].call(b[1], this))
        a.push(this);
    }); 
   return a;
});
Object.prototype.filter = Array.prototype._filter;

定義一個過濾函數,對每個元素進行檢測。如果滿足條件,則返回 true,否則返回 false。最後把過濾函數傳遞給疊代器,即可達到過濾陣列元素的目的。

應用程式碼

定義陣列和一個過濾函數,設計如果引數值大於 4,則返回 true。
var a = [1,2,3,4,5,6,7,8,9];
var f = function (x) {
    if (x > 4) return true;
}
呼叫陣列 a 的原型方法 filter(),並把過濾函數作為引數傳遞給方法 filter()。
var b = a.filter(f);  //呼叫陣列元素過濾方法
console.log(b);  //返回[5,6,7,8,9]