forEach方法的缺点
- 只能依次迭代,不能中途结束
- 不支持返回值
- 不能迭代对象
封装一个each方法能达到的目的
const each=function each(obj,callback){};
- 做了传递参数的类型检测
- 可以迭代数组和对象
- 可以中途结束循环(callback中返回false即可)
- 支持修改原数组或对象中的内容(返回一个新数组,原始数据不变)
- obj可以是数字(创建一个等长度的数组进行迭代)
- 支持类数组按照数组的方式进行处理
- 支持callback中的this迭代原始数据
封装万能each
const isObject = function isObject(obj){
return obj !== null && /^(object|function)$/.test(typeof obj);
}
const isFunction = function isFunction(obj){
return typeof obj === 'function';
}
const isArrayLike = function isArrayLike(obj){
let length = !!obj && 'length' in obj && obj.length;
if(isFunction(obj) || obj === window) return false;
return length === 0 || (typeof length === 'number' && length > 0 && (length - 1) in obj);
}
const each = function each(obj,callback){
if(typeof obj === 'number' && !isNaN(obj)) obj = new Array(obj).fill(null);
if(!isObject(obj)) obj = Object(obj);
if(!isFunction(callback)) throw new TypeError('callback is not a function');
let originObj=obj;
if(Array.isArray(obj) || isArrayLike(obj)){
obj = [...obj];
let i = 0 , len = obj.length , result;
for(; i < len ; i++){
result = callback.call(originObj , obj[i] , i);
if(result === false) break;
obj[i] = result;
}
return obj;
}
obj = {...obj};
let keys = Reflect.ownKeys(obj) , i = 0 , len = keys.length , key , result;
for(; i < len ; i++){
key = keys[i];
result = callback.call(originObj , obj[key] , key);
if(result === false) break;
obj[key] = result;
}
return obj;
}
测试each方法
- 如果obj为数字类型
let num = each(3,(item) => item + 1);
console.log(num)
- 如果obj是字符串(类数组)
let str = each('我爱你中国', function(value , key){
console.log(key , this);
return value;
})
console.log(str);
- 如果obj是数组
let arr = [10 , 20 , 30 , 40 , 50 ,60];
let arr2 = each(arr , (item , index) => {
if(index > 2) return false;
return item * index ;
})
console.log(arr , arr2);
- 如果obj是对象
let obj = {
x:10,
y:20,
[Symbol()]:30
}
let ob2 = each(obj , (value , key) => {
if(key === 'y') return false;
console.log(value , key);
return value * 10;
})
console.log(obj,ob2);