JS工具函数——(searchProperty,clone,getChildren)

JS工具函数

目录

  1. 控制台查找某个对象下深层嵌套的属性或方法,返回路径searchProperty
  2. 深拷贝clone和浅拷贝shallowClone
  3. 扁平数组变tree结构getChildren
  4. 数据求和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)]
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值