这是我参与「第五届青训营 」伴学笔记创作活动的第15天
1.数组API(Array)
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: 从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值
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__;
}
}
原型指向
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;
}
}