JS工具类学习(二)| 青训营笔记

50 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第15天

1.数组API(Array)

image-20230105144320200

1.map()

数组遍历回调

map()方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回

map只进行回调不讨论真假

 function map(arr, callback){
     //声明一个空的数组
     let result = [];
     //遍历数组
     for(let i=@;i<arr.length;i++){
         //执行回调
         result.push(callback(arr[i], i));
     }
     //返回结果
     return result;
 }

map的作用:遍历所有元素逐一进行处理,而后返回一个新的数组

2. reduce()

数组遍历回调

reduce0: 从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值

image-20230105110821261

 function reduce(arr, callback,initValue){
     //声明变量
     let result = initValue;
     //执行回调
     for(let i=@;i<arr.length;i++){
         //初始值未赋值时将第一个元素赋值给result
         if(result === undefined)
         {result = arr[i]; continue;}
         //执行回调
         result = callback(result, arr[i]);
     }
     return result;
 }
 ​

reduce作用:从左到右依次回调,回调结果会保存到下一次回调中

3.filter()

数组遍历回调

对数组进行回调,返回回调结果,比map多一个判断

 function filter(arr,callback){
     //声明空数组
     let result = [];
     //遍历数组
     for(let i=@;i<arr.length;i++){
         //执行回调
         let res = callback(arr[il, i);
         //判断 如果为真则压入到 result结果
         if(res){
             result.push(arr[i]);
         }
     }
     //返回结果
     return result;
 }

4.find()

找一个元素

find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。

 function find(arr, callback){
     //遍历数组
     for(let i=0;i<arr.length;i++){
         //执行回调
         let res = callback(arr[i], i);
         //判断
         if(res){
             //返回当前正在遍历的元素
             return arr[i];
          }
     }
     //如果没有遇到满足条件的 返回 undefined
     return undefined;
 }

5.findlndex()

找一个元素返回索引

findindex(): 找到第一个满足测试函数的元素并返回那个元素的索引,如果找不到则返回-1

 function find(arr, callback){
     //遍历数组
     for(let i=0;i<arr.length;i++){
         //执行回调
         let res = callback(arr[i], i);
         //判断
         if(res){
             //返回当前正在遍历的元素
             return i;
          }
     }
     //如果没有遇到满足条件的 返回 undefined
     return undefined;
 }

6.every()

遍历所有元素符合回调

全为真返回true,否则返回flase

 function every(arr, callback){
     //遍历数组
     for(let i=@;i<arr.length;i++){
         // 执行回调 如果回调执行返回结果为 false
         if(!callback(arr[i], i)){
             return false;
         }
     }
     //如果都满足条件则返回 true
     return true;
 }

一个假全假

7.some()

遍历存在元素符合回调

存在一个真即可返回真

 function every(arr, callback){
     //遍历数组
     for(let i=@;i<arr.length;i++){
         // 执行回调 如果回调执行返回结果为 ture
         if(callback(arr[i], i)){
             return ture;
         }
     }
     //如果都满足条件则返回 flase
     return flase;
 }

一个真全真

8.unique1()/ unique2()/ unique3()数组去重

1.unique1()

方法1: 利用forEach0和indexOf0 说明: 本质是双重遍历效率差些

forEach+indexOf(遍历+查找)=>新建数组遍历旧数组如果新数组中没有,就插入新数据

 function unique(arr){
     //声明一个空数组
     const result = [];
     //遍历原始数组
     arr.forEach(item => {
         //检测 result 数组中是否包含这个元素
         if(result.indexOf(item) === -1) {
             //若没有该元素 则插入到
             result中result.push(item)
         }
     });
     //返回
     return result;
 }

2.unique2()

。方法2:利用forEach0 + 对象容器 。说明: 只需一重遍历,效率高些 以对象作为容器,将数组元素作为下标存入(下标不会重复),当对应的下标不存在时,才插入新元素

 function unique2(arr){
     //声明空数组
     const result = [];
     //声明空对象
     const obj = {};
     //遍历数组
     arr.forEach(item =>{
         if(obj[item]=== undefined)
         {
             //将 item 作为下标存储在 obj 中
             obj[item] = true;result.push(item)
         }
     });
     return result;
 }

3.unique3()

。方法3:利用ES6语法: from + Set 或者 ... + Set 。说明: 编码简洁

以Set作为容器,Set中的元素不可重复

 function unique2(arr){
     return new Set(arr);
 }

9.concat()

数组合并

 function concat(arr,..args){
     //声明一个空数组
     const result = [...arr];
     //遍历数组
     args.forEach(item => {
         //判断 item 是否为数组
         if(Array.isArray(item)){
             result.push(...item);
         }else {
             result.push(item);
         }
     });
     return result;
 }

10.slice()

数组切片(前取后不取)

 function slice(arr,begin, end){
     //若arr长度为0
     if(arr.length === 0){
         return [];
     }
     //判断brgin
     begin = begin || 0;
     if(begin >= arr.length || begin < 0){
         return [];
     }
     //判断end
     end = end || arr.length;
     if(end >= arr.length || begin < end){
         return [];
     }
     //声明一个空数组
     const result = [];
     //遍历对象
     for(let i=@;i<arr.length;i++){
         if(i >= begin && i < end){
             //将下标对应的元素压入数组
             result.push(arr[i]);
         }
     }
     return result;
 }

11.flatten()

数组扁平化(多维数组变一维数组)

 //方式一:使用递归
 function flatten1(arr){
     //声明空数组
     let result = [];
     //遍历数组
     arr.forEach(item => {
         //判断
         if(Array.isArray(item)){
             result = result.concat(flatten1(item));
         }
         else{
             result = result.concat(item);
         }
     });
     return result;
 }
 //方式二:some以及concat
 function flatten2(arr){
     //声明空数组
     let result = [...arr];
     //循环判断 只要存在数组的话就会进行cancat
     whil(result.some(item => Array.isArray(item))){
         result = [].concat(...result);
     }
     return result;
 }

12.chunk() / chunk2()

数组分块,指定拆分成的长度size,每个区块组成小数组,整体组成一个二维数组

 function chunk(arr ,size ){
     //空数组判断
     if(arr.length === 0){
         return [];
     }
     //声明两个变量
     let result = [],
         temp = [];
     //遍历
     arr.forEach(item => {
         //判断temp的长度是否为0 如果为0,就压入result中形成一个=>[[第一次]]=>[[1,2,3],[第二次]...]
         if(temp.length === 0){
             //将temp压入到result中=>[[1,2,3]]
             result.push(temp);
         }
         temp.push(item);
         //满了就清空
         if(temp.length === size){
             temp = [];
         }
     })
 }

13.difference()

得到当前数组中所有不在arr中的元素组成的数组(不改变原数组)

difference([1,2,3,4],[2,3])=>[1,4]

 function difference(arr1, arr2){
     if( arr1.length === 0 || arr2.length === undefine){
         return [];
     }
     if( arr2.length === 0 || arr2.length === undefine){
         return arr1;
     }
     //使arr1中每一个元素进行回调 返回一个arr1包含而arr2中不包含的数组
     arr1.filter(item => !arr2.includes(item));
 }

14.pull()

删除数组中的指定元素,返回数组为被删除的元素,原数组为删除后的数组(改变原数组)

pull([1,3,5,3,7], 2, 7, 3, 7)===>原数组变为[1,5],返回值为[3,3,7]

 function pull(arr,...args){
     //声明空数组 保存删掉的元素
     const result = [];
     //遍历 arr
     for(let i=@;i<arr.length;i++){
         //判断当前元素是否存在于 args 数组中
         if(args.includes(arr[i])){
             //将当前元素的值存入到 result中
             result.push(arr[i]);
             //删除当前的元素(第i个开始删除1个)
             arr.splice(i,1);
             //下标自减 保证指向删除后的下一个数而不是下下个数
             i--;
         }
     }
     //返回数组
     return result;
 }

15.pullAll()

与pull()不同的是输入参数为一个数组

 function pullAll(arr, Array){
     //将数组展开即可
     retrun pull(arr,...Array);
 }

16.drop()

舍弃左边返回数组

 function drop(arr, size){
     //过滤原数组,产生新数组
     retrun arr.filter((value, index) => {index >= size});
 }

17.dropRight()

舍弃右边返回数组

 function dropRight(arr, size){
      //过滤原数组,产生新数组
     retrun arr.filter((value, index) => {index <= arr.length - size});
 }

2.对象API

1.对象实例化

 function newInstance(Fn,...args){
     //1。创建一个新对象
     const obj = ();
     //2. 
     const result = Fn.call(obj, ...args);
     //修改新对象的原型对象
     obj._proto___ = Fn.prototype;
     //3.返回新对象
     return result instanceof Object ? result : obj;
 }

2.比对对象类型instanceof

用例:检测对象原型对象是不是OBJ的原型链上的某个对象,如果是返回true,不是返回false

 //检测
 console.log(p instanceof Person);
 ​
 function myInstanceof(obj, Fn){
     //获取函数的显式原型
     let prototype = Fn.prototype;
     //获取 obj 的隐式原型对象
     let proto = obj.__proto__;
     //遍历原型链
     while(proto){
     //检测原型对象是否相等
         if(prototype === proto){
             return true;
         }
         //如果不等于就继续向上遍历
         proto = proto.__proto__;
     }
 }

image-20230106152940052

原型指向

3,.对象合并mergeObject

 function mergeobject(...objs){
     //声明一个空对象
     const result = {};
     //遍历所有的参数对象
     objs.forEach(obj => {
          //获取当前对象所有的属性
         Object.keys(obj).forEach(key => {
             //检测 result 中是否存在 key 属性
             if(result.hasOwnProperty(key)){
                 result[key] = [].concat(result[key],obj[key]);
             }else{
                 //如果没有 则直接写入
                 result[key] = obj[key];}
         }
     });
         return result;
 });

7.数据拷贝

1.深拷贝、浅拷贝区别(深拷贝:有新对象生成,浅拷贝:引用 )

 纯语言表达:
     浅拷贝: 只是复制了对象属性或数组元素本身(只是引用地址值)。
     深拷贝: 不仅复制了对象属性或数组元素本身,还复制了指向的对象(使用递归)
 举例说明: 拷贝persons数组(多个人对象的数组)
     浅拷贝: 只是拷贝了每个person对象的引用地址值, 每个person对象只有一份
     深拷贝: 每个person对象也被复制了一份新的

2.浅拷贝

方法一

 function clone1(target){
     //类型判断 {对象} [数组] nu11
     if(typeof target === 'object' && target){
        //判断数据是否为数组
         if(Array.isArray(target)){
             return [...target];
         }else{
             return {...target};
         }
     }else{
         return target;
     }
 }

方法二

 function clone2(target){
     if(typeof target === 'object' && target !== null){
         //创建一个容器
         const result = Array.isArray(target) ? [] : {};
         //遍历 target 数据
         for(let key in target) {
             //判断当前对象身上是否包含该属性
             if(target.hasOwnProperty(key)){
             //将属性设置到 result 结果数据中
             result[key] = target[key];
             }
         }
         return result;
     }else{
         return  target;
     }
 }

3.深拷贝

1、大众乞丐版

数据json化=>再封装不能拷贝多维数据以及方法

 function deepClone1(target){
     //通过数据创建 JSON 格式的字符串
     let str = JSON.stringify(target);
     //将 JSON 字符串创建为 JS 数据
     let data = JSON.parse(str);
     return data;
 }

2、递归拷贝

一层一层的拷贝(不能循环引用)

 function deepClone2(target){
     //检测数据类型
     if(typeof target === 'object' && target !== null){
         //创建一个容器
         const result = Array.isArray(target) ? [] :{};
         //遍历对象
         for(let key in target){
             //检测该属性是否为对象本身的属性(不能拷贝原型对象的属性)
             if(target.hasOwnProperty(key)){
                 result[key] = deepClone2(target[key]);
             }
         }
         return result;
     }
     //其他数据类型(字符串、数字)
     else{
         return target;
     }
 }

使用Map解决循环引用

 function deepClone3(target,map = new Map()){
     //检测数据类型
     if(typeof target === 'object' && target !== null){
         let cache = map.get(target);
         if(cache){
             return cache;
         }
         //创建一个容器
         const result = Array.isArray(target) ? [] :{};
         //遍历对象
         for(let key in target){
             //检测该属性是否为对象本身的属性(不能拷贝原型对象的属性)
             if(target.hasOwnProperty(key)){
                 result[key] = deepClone3(target[key], map);
             }
         }
         return result;
     }
     //其他数据类型(字符串、数字)
     else{
         return target;
     }
 }

3、优化版深拷贝