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
总结有错还请指出,谢谢