1、扁平数组转Tree
方式一
/**
* @description 扁平数组转Tree(递归)
* @param {*} arr 数组
* @returns
*/
export const getTree1 = (arr = [], pid = 0) => {
const res = []
arr.forEach(item => {
if (pid === item.pid) {
// 求子孩子
item['children'] = getTree1(arr, item.id)
res.push(item)
}
})
return res
}
方式二
/**
* @description 扁平数组转Tree(map)
* @param {*} arr 数组
*/
export const getTree2 = (arr = []) => {
const res = []
const map = new Map()
arr.forEach(item => {
map.set(item.id, { ...item, children: [] })
})
arr.forEach(item => {
const [parent, self] = [map.get(item.pid), map.get(item.id)]
parent ? parent.children.push(self) : res.push(self)
})
return res
}
2、深拷贝
方式一
/**
* @description 深拷贝(递归)
* @param {*} origin
* @returns
*/
export const deepClone1 = (origin = {}) => {
let target = {}
for (let prop in origin) {
if (origin.hasOwnProperty(prop)) {
if (origin[prop] && typeof origin[prop] === 'object') {
target[prop] = origin[prop].constructor === Array ? [] : {}
deepClone1(origin[prop], target[prop])
} else {
target[prop] = origin[prop]
}
}
}
return target
}
方式二
/**
* @description 深拷贝(JSON方法)
* @param {*} origin
* @returns
*/
export const deepClone2 = (origin) => {
return JSON.parse(JSON.stringify(origin))
}
3、数组乱序
/**
* @description 数组乱序
* @param {*} arr
* @returns
*/
export const arrOutOfOrder = (arr = []) => {
return arr.sort(() => Math.random() - 0.5)
}
4、数组去重
/**
* 数组去重
* @param {*} arr
* @returns
*/
export const unique = (arr = []) => {
return [...new Set(arr)]
}
5、获取数组最大值
/**
* @description 获取数组最大值
* @param {*} arr
* @returns
*/
export const getMax = (arr = []) => {
return Math.max(...arr)
}
6、获取数组最小值
/**
* @description 获取数组最小值
* @param {*} arr
* @returns
*/
export const getMin = (arr = []) => {
return Math.min(...arr)
}
7、合并数组或对象
/**
* @description 合并数组或对象(...扩展运算符)
*/
const mergeArrOrObj = () => {
// 合并数组(相同元素不会进行覆盖)
const [arr1, arr2, arr3] = [[1], [2, 3], [3]]
console.log([...arr1, ...arr2, ...arr3])
// 合并对象(相同属性,后者覆盖前者)
const [obj1, obj2, obj3] = [{ name: 'mei' }, { name: 'meibo', age: 23 }, { sex: 'male' }]
console.log({ ...obj1, ...obj2, ...obj3 })
}
8、过滤数组中的false值
/**
* @description 过滤数组中的false值(null、undefined、false、''、0)
* @param {*} arr
* @returns
*/
export const filterF = (arr = []) => {
return arr.filter(Boolean)
}
9、数组求和
/**
* @description 数组求和
* @param {*} arr
* @returns
*/
export const getSumOfArr = (arr = []) => {
return arr.reduce((preRes, curV) => preRes + curV)
}
10、统计数组中各元素的个数
/**
* @description 统计数组中各元素的个数
* @param {*} arr
* @returns
*/
export const getEleNumOfArr = (arr = []) => {
return arr.reduce((preRes, curV) => {
preRes[curV] ? preRes[curV]++ : preRes[curV] = 1
return preRes
}, {})
}
11、ES6+ 数组方法
/**
* @description ES6+ 数组方法
*/
const useArrFn = () => {
const arr = [0, 1, 2]
// 1、forEach(遍历数组)
// 参数:cb(遍历项、索引、数组本身)
arr.forEach((item, index, arr) => {
console.log(item, index, arr)
})
// 2、map(返回经处理后的新数组)
// 参数:cb(遍历项、索引、数组本身)
const arrMap = arr.map((item, index, arr) => item ** 2)
console.log(arrMap)
// 3、filter(过滤数组)
// 参数:cb(遍历项、索引、数组本身)
const arrFilter = arr.filter((item, index, arr) => item > 2)
console.log(arrFilter)
// 4、some(判断条件只要有一个为true,则返回true;全为false,则返回false)
// 参数:cb(遍历项、索引、数组本身)
const arrSome = arr.some((item, index, arr) => item > 0)
console.log(arrSome)
// 5、every(判断条件全为true,则返回true;有一个为false,则返回false)
// 参数:cb(遍历项、索引、数组本身)
const arrEvery = arr.every((item, index, arr) => item > 0)
console.log(arrEvery)
// 6、reduce(求和、统计元素出现的个数)
// 参数:cb(上一次的返回值、当前元素、当前元素索引、数组本身)、preRes的初始值(若指定初始值,则curV从数组第一项开始;未指定,preRes取第一项,curV从数组第二项开始)
const resReduce = arr.reduce((preRes, curV, curIndex, arr) => {
return preRes + curV
}, 6)
console.log(resReduce)
// 7、find(返回第一个满足条件的元素,没有则返回undefined)
// 参数:cb(遍历项、索引、数组本身)
const resFind = arr.find((item, index, arr) => item === 0)
console.log(resFind)
// 8、findIndex(返回第一个满足条件元素的索引,没有则返回-1)
// 参数:cb(遍历项、索引、数组本身)
const resFindIndex = arr.findIndex((item, index, arr) => item === 0)
console.log(resFindIndex)
// 9、includes(判断数组中是否包含一个指定的值,若存在,则返回true;不存在,则返回false)
// 参数:指定元素、位置索引(从此处开始搜索,若 < 0 ,则搜索全部)
const resIncludes = arr.includes(0)
console.log(resIncludes)
// 10、flat(数组的扁平化,数组空项会被移除)
// 参数:提取嵌套数组的深度(默认为1,传入 Infinity 则展开任意深度的嵌套数组)
const origin = [1, 2, [3, 4, [5, [6, 7]]], ,]
const arrFlat = origin.flat(Infinity)
console.log(arrFlat)
// 11、flatMap(相当于flat + map)
const origin1 = ['1 2 3', '4 5 6']
const arrFlatMap = origin1.flatMap((item, index, arr) => item.split(' '))
console.log(arrFlatMap)
// 等同于
const arrFlatMap1 = origin1.map(item => item.split(' ')).flat()
console.log(arrFlatMap1)
}
12、ES6+ 对象方法
/**
* @description ES6+ 对象方法
*/
const useObjFn = () => {
const obj = {
name: 'mei',
age: 23,
sex: 'male',
sayHello () { console.log(`hi,my name is ${this.name}`) }
}
// 1、Object.key(获取对象的键的集合)
console.log(Object.keys(obj))
// 2、Object.values(获取对象的值的集合)
console.log(Object.values(obj))
// 3、Object.entries(获取对象的键值对的集合)
console.log(Object.entries(obj))
// 4、Object.freeze(冻结对象,被冻结的对象将不可被修改)
Object.freeze(obj)
// Uncaught TypeError: Cannot assign to read only property 'age' of object '#<Object>'
// obj.age = 18
// 5、Object.fromEntries(与entries相反,将键值对的集合转为对象)
const key_val = [['name', 'mei'], ['age', 23]]
console.log(Object.fromEntries(key_val))
}
13、随机生成20位序列值
/**
* @description 随机生成20位序列值:当前时间 + 六位随机数
* @description 需要具备 dayjs库
* @returns
*/
export const genRandowId = () => {
const curTime = dayjs().format('YYYYMMDDHHmmss')
let randomSixStr = ''
for (let i = 0; i < 6; i++) {
randomSixStr += String(Math.floor(Math.random() * 10))
}
return curTime + randomSixStr
}
14、页面滚动
/**
* @description 页面滚动
* @param {*} top 高度
* @param {*} left 宽度
* @param {*} behavior 行为 smooth(平滑)
*/
export const scrollTo = (top = 0, left = 0, behavior = 'smooth') => {
document.documentElement.scrollTo({
top,
left,
behavior
})
}
15、去除数字之外的所有字符
/**
* @description 去除数字之外的所有字符
* @param {*} str
* @returns
*/
export const getOnlyNumOfStr = (str = '') => {
return str.replace(/\D/g, '')
}
16、反转字符串
/**
* @description 反转字符串(按字符或单词)
* @param {*} str
* @param {*} type char(字符)、word(单词)
* @returns
*/
export const reverseStr = (str = '', type = 'char') => {
const typeMap = {
'char': () => '',
'word': () => ' '
}
return str.split(typeMap[type]()).reverse().join(typeMap[type]())
}
17、保留n位小数
/**
* 保留n位小数
* @param {*} num
* @param {*} n
* @returns
*/
export const getFixedNum = (num, n = 2) => {
num = Number(num)
if (isNaN(num)) return '-'
return Number(num.toFixed(num, n))
}
18、?. 、??、||=、&&=
/**
* @description ?.(可选链操作符:读取对象的深处属性,若不存在不会报错,返回undefined,仅用于读取属性,不可用于赋值)
* @description ??(合并空值操作符:操作符左侧值为null或undefined时,返回操作符右侧值)
* @description ||=(a ||= b 等同于 a || a = b ,a为虚值时,给a赋值)
* @description &&=(a &&= b 等同于 a && a = b ,a为实值时,给a赋值)
*/
const useOprSymbol = () => {
// 1、?.
const obj = {
name: 'mei'
}
// undefined
console.log(obj.prop?.sex)
// Uncaught TypeError: Cannot read properties of undefined(reading 'sex')
// console.log(obj.prop.sex)
// Uncaught SyntaxError: Invalid left - hand side in assignment
// obj?.name = 'meibo'
// 2、??
const [flag1, flag2, flag3] = [null, undefined, 'meibo']
console.log(flag1 ?? 'mei')
console.log(flag2 ?? 'mei')
console.log(flag3 ?? 'mei')
// 3、||=(无则赋值)
obj.age ||= 23
console.log(obj) // {name: 'mei', age: 23}
// 4、&&=(有则赋值)
obj.age &&= 18
obj.sex &&= 'male'
console.log(obj) // {name: 'mei', age: 18}
}
19、一种数据存储方式
/**
* 一种数据存储方式
*/
const useObjMap = () => {
const colorMap = {
'需求': () => '#409EFF',
'设计': () => '#67C23A',
'开发': () => '#E6A23C',
'测试': () => '#F56C6C',
'部署': () => '#909399'
}
console.log(colorMap['开发']())
}
20、for await of
/**
* @description for await of(循环遍历异步结果)
*/
const useForAwaitOf = async () => {
const fn = timeout => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(timeout)
}, timeout)
})
}
// 正常用法
const res1 = await fn(2000)
console.log(res1)
const res2 = await fn(1000)
console.log(res2)
const res3 = await fn(3000)
console.log(res3)
// for await of 用法
const arr = [fn(2000), fn(1000), fn(3000)]
for await (let res of arr) {
console.log(res)
}
}