forEach
是一个迭代器,负责遍历(Array、Set、Map)可迭代对象;但是 for 循环是一种循环机制,只能通过它遍历出数组
iterable
类型;Array
、Set
、Map、String
、arguments
、NodeList
都属于iterable
,拥有【Symbol.iterator】方法。forEach要求使用同步函数
const sleep = (ms) => {return new Promise((resolve) => {setTimeout(resolve, ms)})
}
const arr = [() => console.log("start"),() => sleep(1000),() => console.log(1),() => sleep(1000),() => console.log(2),() => sleep(1000),() => console.log(3),() => sleep(1000),() => console.log("end")
]async function run(arr) {for (let i = 0; i < arr.length; i++) {await arr[i]()}
}
run(arr)// 打印start,1秒后打印1,再过1秒打印2,再过1秒打印3,再过1秒,打印end
手写forEach
let obj = {};
Array.prototype.syncForEach = function (callback, args) {const _arr = this; // 因为调用的方式 [1,2,3].asyncForEach this指向数组const isArray = Array.isArray(_arr); // 判断调用者是不是数组const _args = args ? Object(args) : obj; //对象化if (!isArray) {throw new TypeError("the caller must be a array type!")}for (let i = 0; i < _arr.length; i++) {callback.call(_args, _arr[i])}
}const sleep = (ms) => {return new Promise((resolve) => {setTimeout(resolve, ms)})
}
const arr = [() => console.log("start"),() => sleep(1000),() => console.log(1),() => sleep(1000),() => console.log(2),() => sleep(1000),() => console.log(3),() => sleep(1000),() => console.log("end")
]
arr.syncForEach(async(fn)=>{await fn()
})
手写asyncForEach
let obj = {};
Array.prototype.asyncForEach = async function (callback, args) {const _arr = this; // 因为调用的方式 [1,2,3].asyncForEach this指向数组const isArray = Array.isArray(_arr); // 判断调用者是不是数组const _args = args ? Object(args) : obj; //对象化if (!isArray) {throw new TypeError("the caller must be a array type!")}for (let i = 0; i < _arr.length; i++) {await callback.call(_args, _arr[i])}
}const sleep = (ms) => {return new Promise((resolve) => {setTimeout(resolve, ms)})
}
const arr = [() => console.log("start"),() => sleep(1000),() => console.log(1),() => sleep(1000),() => console.log(2),() => sleep(1000),() => console.log(3),() => sleep(1000),() => console.log("end")
]
arr.asyncForEach(async(fn)=>{await fn()
})
for 和 forEach语法区别
arr.forEach((self,index,arr) =>{},this)// 举例
let arr = ['a', 'b', 'c'];
let person = {name: 'Jayson'
};
arr.forEach((self, index, arr) => {console.log(`当前元素为${self}索引为${index},属于数组${arr}`);console.log(this.name += '真帅');
}, person)// 当前元素为a索引为0,属于数组a,b,c
// undefined真帅
// 当前元素为b索引为1,属于数组a,b,c
// undefined真帅真帅
// 当前元素为c索引为2,属于数组a,b,c
// undefined真帅真帅真帅
let arr = ['a', 'b', 'c'];
let person = {name: 'Jayson'
};
arr.forEach(function (self, index, arr) {console.log(`当前元素为${self}索引为${index},属于数组${arr}`);console.log(this.name += '真帅');
}, person)// 当前元素为a索引为0,属于数组a,b,c
// Jayson真帅
// 当前元素为b索引为1,属于数组a,b,c
// Jayson真帅真帅
// 当前元素为c索引为2,属于数组a,b,c
// Jayson真帅真帅真帅
try {let arr = [1, 2, 3, 4];arr.forEach(function (item, index) {//跳出条件if (item === 3) {throw new Error("LoopTerminates");}console.log('item', item);// item 1// item 2});
} catch (e) {if (e.message !== "LoopTerminates") throw e;console.log('e.message', e.message); // e.message LoopTerminates
};
map迭代器和filter迭代器都是生成新数组;
性能比较:for > forEach > map
原因:
var foo = {hasOwnProperty: function() {return false;},bar: 'Here be dragons'
};foo.hasOwnProperty('bar'); // 始终返回 false// 如果担心这种情况,
// 可以直接使用原型链上真正的 hasOwnProperty 方法
({}).hasOwnProperty.call(foo, 'bar'); // true// 也可以使用 Object 原型上的 hasOwnProperty 属性
Object.prototype.hasOwnProperty.call(foo, 'bar'); // true