陣列的forEach,map,filter,reduce,reduceRight,every,some方法

Wament發表於2019-04-20

forEach

基本介紹

forEach按照升序為陣列中的每一項執行依此callback函式,那些已刪除或未初始化的項將被跳過(被顯式宣告為undefined的同樣會被處理)

var a = [1,2, ,3], b = [1,2,undefined,3];
a.forEach(function(item){
    console.log(item);
});
//依次輸出1,2,3

b.forEach(function(item){
    console.log(item);
});
//依此輸出1,2,undefined,3
複製程式碼

arr.forEach(callback[, thisArg]);

callback:為陣列中每個元素執行的函式,且總是返回undefined
currentValue:正在處理的當前元素
(可選)index:正在處理的當前元素的索引
(可選)array:正在處理的陣列
(可選)thisArg:執行callback時用作this的值

遍歷範圍

forEach遍歷的範圍在第一次呼叫callback前就會確定

var a = [1,2];
a.forEach(function(current, i, arr){
    arr.push(current);
    console.log(current);
})
//依次列印1,2
複製程式碼

自己做了以下的測試

var a = [1, 2,,3];
var count = 0;
a.forEach(function (current, i, arr) {
    count++;
})
console.log(count);//輸出3

var a = [1, 2,,3];
var count = 0;
a.forEach(function (current, i, arr) {
    arr[i+1] = current+1;
    count++;
})
console.log(count);//輸出4
複製程式碼

上述的程式碼跟之前總結的有點不太一樣啊?!forEach遍歷的範圍不是在第一次呼叫callback前就確定的嗎?那那些沒有初始化的為什麼還會執行呢?難道是我理解錯了?
我思考了一下,覺得forEach方法的執行是這樣的:

首先會根據陣列的長度來確認迴圈的次數,這裡是4次
每次callback執行之前,都會去判斷當前處理的元素是否已定義,如果未定義,那麼不會執行callback直接跳到下一個處理的元素

forEach遍歷的值是實時的,即如果已經存在的值被改變,則傳遞給callback的值是forEach遍歷到他們那一刻的值

var a = [1,2];
a.forEach(function(current, i, arr){
    arr[i+1] = current;
    console.log(current);
})
//依次列印1,1
複製程式碼

以上的執行過程也是符合前面的總結的

簡單實現

Array.prototype.fakeForEach = function(fn, thisArg){
    let arr = this;
    let len = arr.length;
    for(let i=0; i<len; i++){
        if(i in arr){//判斷當前的index是否已初始化
            fn.call(thisArg, arr[i], i, arr);
        }
    }
}
複製程式碼

map

基本介紹

map方法建立一個新的陣列,其結果是該陣列中每一個元素都呼叫一個提供的函式後返回的結果。

var a = [1,2,3];
var aa = map((current)=>{
    return current*current;
});
console.log([1,4,9]);
複製程式碼

arr.map(callback[, thisArg]);同forEach

遍歷範圍同forEach

相關題目

['1','2','3'].map(parseInt);//結果是[1,NaN,NaN]   
複製程式碼

parseInt(string, radix);//該函式返回以radix未基數解析的string整數
執行以上程式碼時具體步驟如下

parseInt('1', 0);//預設以解析十進位制返回1
parseInt('2', 1);//1進位制中沒有2,返回NaN
parseInt('3', 2);//2進位制中沒有3,返回NaN
返回[1,NaN,NaN]

簡單實現

Array.prototype.fakeMap = function(fn, thisArg){
    let arr = this;
    let len = arr.length;
    let newArr = new Array(len);
    for(let i=0; i<len; i++){
        if(i in arr){//判斷當前的index是否已初始化
            newArr[i] = fn.call(thisArg, arr[i], i, arr);
        }
    }
    return newArr;
}
複製程式碼

reduce實現map

Array.prototype.fakeMap = function(fn, thisArg){
    let arr = this;
    let newArr = arr.reduce(function (newArr, current, i, arr){
        let o = fn.call(thisArg, current, i, arr);
        newArr.push(o);
        return newArr;
    },[])
    return newArr;
}
複製程式碼

filter

基本介紹

filter方法建立一個新的陣列,其包含執行callback後返回值為true的所有元素

let arr = [1,2,3];
var newArr = arr.filter(function(item, i, arr){
    return item != 2;
});
newArr;//[1,3]
複製程式碼

arr.filter(callback[, thisArg]);同forEach

遍歷範圍同forEach

簡單實現

Array.prototype.fakeFilter = function(fn, thisArg){
    let arr = this;
    let len = arr.length;
    let newArr = [];
    for(let i=0; i<len; i++){
        if(i in arr){//判斷當前的index是否已初始化
            if(fn.call(thisArg, arr[i], i, arr)){
                newArr.push(arr[i])
            }
        }
    }
    return newArr;
}
複製程式碼

reduce

基本介紹

reduce方法按升序對陣列中每個元素執行callback,將accumulator賦值為callback返回結果,返回最後的accumulatorreduce返回值

let arr = [1,2,3];
//對arr陣列求和
let result = arr.reduce(function(accumulator, current, i, arr){
    return accumulator+current;
});
result;//6
複製程式碼

arr.reduce(callback(accumulator, currentValue[ index [,array]]) [,initialValue]);

callback:為陣列中每個元素執行的函式,且總是返回undefined
accumulator:累加器,它是上一次呼叫回撥函式時返回的累積值
currentValue:正在處理的當前元素
(可選)index:正在處理的當前元素的索引
(可選)array:正在處理的陣列
(可選)initialValue:作為第一次執行callback時的值
返回值為最後一次執行callback的返回值

遍歷範圍

大體上與forEach相同,遍歷流程不同之處如下

初始化執行次數n,有initialValue則賦值給accumulator,沒有則arr[0]賦值給accumulator
執行callback,將返回值賦值給accumulator × n
將最後一次執行callback的返回值返回

應用

按順序執行Promise

function runPromiseInOther(promiseArr, initialValue){
    return promiseArr.reduce(function(result, current){
            return result.then(current);
        }, Promise.resolve(initialValue)
    );
}
function p1(lastValue){
    return new Promise(function(resolve, reject){
        console.log(lastValue);
        resolve(lastValue * 10);
    })
}
function p2(lastValue){
    return new Promise(function(resolve, reject){
        console.log(lastValue);
        resolve(lastValue * 100)
    })
}
runPromiseInOther([p1,p2], 1)
    .then(console.log);
//依次輸出1,10,1000
複製程式碼

簡單實現

arr.prototype.reduce(function(a, c, i, arr){return a+c;}, initialValue)
Array.prototype.fakeReduce = function(fn, initialValue){
    let arr = this;
    let len = arr.length;
    let i=0, result;
    if(arguments.length == 1){
        result = arr[0];
        i=1
    }else{
        result = initialValue;
    }
    for(; i<len; i++){
        if(i in arr){
            result = fn(result, arr[i], i, arr);
        }
    }
    return result;
}
複製程式碼

every

基本介紹

every() 方法測試陣列的所有元素是否都通過了指定函式的測試,如果測試callback有返回false則立即返回,後續的程式碼不會被執行

let arr = [1,2,3];
console.log(
    arr.every(function(current){
        return current < 10;
    })
);//輸出true
複製程式碼

arr.every(callback[, thisArg]);同forEach

遍歷範圍同forEach

簡單實現

Array.prototype.fakeEvery = function(fn, thisArg){
    let arr = this;
    let len = arr.length;
    for(let i=0; i<len; i++){
        if(i in arr){//判斷當前的index是否已初始化
            if(!fn.call(thisArg, arr[i], i, arr)){
                return false;
            }
        }
    }
    return true;
}
複製程式碼

some

基本介紹

some()方法測試是否至少有一個元素通過由提供的函式實現的測試,如果測試callback有返回true則立即返回,後續的程式碼不會被執行。

let arr = [1,2,3];
console.log(
    arr.some(function(current){
        return current < 2;
    })
);//輸出true
複製程式碼

arr.some(callback[, thisArg]);同forEach

遍歷範圍同forEach

簡單實現

Array.prototype.fakeEvery = function(fn, thisArg){
    let arr = this;
    let len = arr.length;
    for(let i=0; i<len; i++){
        if(i in arr){//判斷當前的index是否已初始化
            if(fn.call(thisArg, arr[i], i, arr)){
                return true;
            }
        }
    }
    return false;
}
複製程式碼

總結

  1. 不能使用break來跳出迴圈
  2. 都是按照升序來遍歷的
  3. 執行流程大致相同,具體看forEach的分析
  4. 實現的思路為len初始化,for實現遍歷,in判斷是否已初始化,fn.call呼叫函式

參考材料:MDN
總結有錯還請指出,謝謝

相關文章