JS工具函数
目录
- 控制台查找某个对象下深层嵌套的属性或方法,返回路径searchProperty
- 深拷贝clone和浅拷贝shallowClone
- 扁平数组变tree结构getChildren
- 数据求和getArrSum
searchProperty
/*
查询对象、数组的属性或方法,返回其路径
使用场景:已知属性名且唯一,查找API,返回其路径
*/
let arr = [];
function searchProperty(obj,count,res) {
if(count > 8) { // 迭代次数
return 0
}
count++
if(obj instanceof Array) { // 数组
let len = Math.min(obj.length,5) // 只找前五个
for(let i=0; i<len; i++) {
if(obj[i] == res) {
return 1
}
if(searchProperty(obj[i],count,res)) {
arr.unshift(i)
return 1
}
}
}else if(obj instanceof Object) {
for(let k in obj) {
if(k == res) {
return 1
}
if(searchProperty(obj[k],count,res)) {
arr.unshift(k)
return 1
}
}
}else return 0
}
// e.g. searchProperty({a:1,b:{a1:1,bb:[1,2,{c:1}]}},0,"c")
// console.log(arr)
clone
参考 https://mp.weixin.qq.com/s/lgdMXsQJUX363cEfEtK0KQ
深拷贝和浅拷贝区别:
shallowClone
function shallowClone(source) {
var target = {};
for(var i in source) {
if (source.hasOwnProperty(i)) {
target[i] = source[i];
}
}
return target;
}
clone
加上递归即可,判断是对象就递归赋值
function clone(source) {
var target = {};
for(var i in source) {
if (source.hasOwnProperty(i)) {
if (typeof source[i] === 'object') {
target[i] = clone(source[i]); // 注意这里
} else {
target[i] = source[i];
}
}
}
return target;
}
也可简单利用JSON
function cloneJSON(source) {
return JSON.parse(JSON.stringify(source));
}
优化
存在问题:1. 参数检验非对象跳过,2. 判断是否为对象不严谨,3. 没有考虑数组,4. 递归爆栈, 5. 循环引用
// 保持引用关系
function cloneForce(x) {
// =============
const uniqueList = []; // 用来去重
// =============
let root = {};
// 循环数组
const loopList = [
{
parent: root,
key: undefined,
data: x,
}
];
while(loopList.length) {
// 深度优先
const node = loopList.pop();
const parent = node.parent;
const key = node.key;
const data = node.data;
// 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素
let res = parent;
if (typeof key !== 'undefined') {
res = parent[key] = {};
}
// =============
// 数据已经存在
let uniqueData = find(uniqueList, data);
if (uniqueData) {
parent[key] = uniqueData.target;
continue; // 中断本次循环
}
// 数据不存在
// 保存源数据,在拷贝数据中对应的引用
uniqueList.push({
source: data,
target: res,
});
// =============
for(let k in data) {
if (data.hasOwnProperty(k)) {
if (typeof data[k] === 'object') {
// 下一次循环
loopList.push({
parent: res,
key: k,
data: data[k],
});
} else {
res[k] = data[k];
}
}
}
}
return root;
}
function find(arr, item) {
for(let i = 0; i < arr.length; i++) {
if (arr[i].source === item) {
return arr[i];
}
}
return null;
}
getChildren
// 扁平数组变tree结构,除去pid=0,各对象应放在其pid值对应的id对象的children里
function getChildren(arr,res,pid) {
for(const item of arr){
if(item.pid === pid){
const newItem = {...item, children:[]}
res.push(newItem)
// console.log(res)
getChildren(arr, newItem.children, item.id)
}
}
}
let arr = [
{id: 1, name: '部门1', pid: 0},
{id: 2, name: '部门2', pid: 1},
{id: 3, name: '部门3', pid: 1},
{id: 4, name: '部门4', pid: 3},
{id: 5, name: '部门5', pid: 4},
]
getChildren(arr,[],0)
优化
//先把数据转成Map去存储,之后遍历的同时借助对象的引用,直接从Map找对应的数据做存储。不同点在遍历的时候即做Map存储,有找对应关系
function arrayToTree(items) {
const result = []; // 存放结果集
const itemMap = {}; //
for (const item of items) {
const id = item.id;
const pid = item.pid;
if (!itemMap[id]) {
itemMap[id] = {
children: [],
}
}
itemMap[id] = {
...item,
children: itemMap[id]['children']
}
const treeItem = itemMap[id];
if (pid === 0) {
result.push(treeItem);
} else {
if (!itemMap[pid]) {
itemMap[pid] = {
children: [],
}
}
itemMap[pid].children.push(treeItem)
}
}
return result;
}
getArrSum
数组求和
function getArrSum (arr) {
return arr.reduce((prev, cur)=>{ // prev表示上一次调用回调时的返回值,或者初始值init
// cur 表示当前正在处理的数组元素;
return prev+cur
},0) // 0为初始值init,可以不传
}
数组求最大值
function getArrMax (arr) {
return arr.reduce((prev, cur)=>{
return Math.max(prev,cur)
})
}
数组去重
function getArrSet (arr) {
return [...new Set(arr)]
}