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
返回結果,返回最後的accumulator
為reduce
返回值
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;
}
複製程式碼
總結
- 都不能使用break來跳出迴圈
- 都是按照升序來遍歷的
- 執行流程大致相同,具體看forEach的分析
- 實現的思路為len初始化,for實現遍歷,in判斷是否已初始化,fn.call呼叫函式
參考材料:MDN
總結有錯還請指出,謝謝