实现forEach
forEach
参数
- 回调函数
callbackFn(当前元素element,索引index,array调用forEach()的数组本身)
回调函数的参数是按顺序传入的 如果只传入索引需要占位符
this.Arg指定回调函数的this指向
没有返回值
返回undefined 不能继续链式调用(map区别)
- 图上是指 在回调函数有返回值的情况下 forEach方法也是没有返回值的
- 回调函数是箭头函数的情况下 箭头函数后面的表达式会被自动作为返回值
不更改原数组
基于原数组长度遍历
稀疏数组的空槽不执行回调函数
这里稀疏数组是指数组可以包含“空槽”,这与用值 undefined 填充的槽不一样
槽的行为就像填入了undefined一样
判断是否遍历到空槽目前先用
undefined来判断 但是有undefined元素的数组也不会执行回调函数 这个判断方式不够严谨 等我学到更合适的方法再进行分享
创建方式和不执行回调函数如下图所示
实现
- 首先把原数组的长度保存
- 然后考虑thisArg参数 利用
||运算符 没传入的情况就指向全局window - 然后遍历数组 如果这个元素不是
undefined就call方法执行参数顺序为(this指向 元素的值 索引 和传入数组)
Array.prototype.myForeach = function (callback, thisArg) {
//基于原数组长度
let len = this.length
thisArg = thisArg || window
for (let i = 0; i < len; i++) {
if (this[i] !== undefined) {
callback.call(thisArg, this[i], i, this)
}
}
}
- 以下是测试用例
//回调函数参数顺序
arr.myForeach((_, index) => console.log(`index ${index}`))
arr.myForeach(() => {
console.log('遍历');
})
arr.myForeach((value) => console.log('value', value))
let num = {
count: 0
}
//thisArg参数
arr.myForeach(function () {
this.count++
}, num)
console.log(num.count); //5
//基于原数组操作
arr.myForeach((item, index) => {
console.log(item);//打印原数组
arr.push(index + 5)
})
console.log('不改变原数组', arr,);
//此时原数组改变[1, 2, 3, 4, 2, 5, 6, 7, 8, 9]
//稀疏数组的情况
const arr1 = [1, 2]
arr1[5] = 5
arr1.myForeach((item) => {
console.log(item); //只打印有值的元素
})
实现map
map
参数
和forEach()一样
- 回调函数callbackFn(正在处理的元素element,索引index,调用的数组本身array)
- thisArg执行回调函数this的值
注意 有thisArg参数的时候不能用箭头函数当作回调函数
返回新数组
map方法返回新数组 这是和forEach的区别
forEach没有返回值
稀疏数组的空槽不执行回调函数
这里也和forEach一样
稀疏数组调用
filterforEach和map方法都不执行回调函数
基于原数组长度
基于第一次遍历的数组长度
注意这里的
undefined是五个控制台打印表达式的返回值> 注意写对象的属性名
实现
这里和forEach的区别是创建newArr新数组存放map的返回值
不用
push方法是为了防止稀疏数组情况下索引混乱
//map()
Array.prototype.myMap = function (callback, thisArg) {
thisArg = thisArg || window
let len = this.length
let newArr = []
for (let i = 0; i < len; i++) {
if (this[i] !== undefined) {
newArr[i] = callback.call(thisArg, this[i], i, this)
}
}
return newArr
}
- 以下是测试用例
const mapArr = [1, 2, 3]
//返回新数组
// mapArr.myMap((value) => value + 1) // [2, 3, 4]
//空属性不执行回调函数
mapArr[5] = 5
mapArr.myMap((value) => value + 1) //[2, 3, 4, 空属性 × 2, 6]
//thisArg参数
let mapArr1 = [1, 2, 3]
let numMap = {
count: 0
}
//注意箭头函数的this指向外层作用域的this
mapArr1.myMap(function () {
this.count++
console.log(this);
}, numMap)
console.log(numMap);//{count: 3}