Javascript 常见手写题

442 阅读5分钟

数组扁平化

function flatter(arr){
    while(arr.some(Array.isArray)){
        arr = [].concat(...arr)
    }
}
function flatter(arr){
    return arr.reduce( (pre,cur) => {
        Array.isArray(cur)?[...pre,...flatter(cur)]:[...pre,cur]
    },[])
}
Array.prototype.flat = function(){
    return [].concat(...this.map( item => (Array.isArray(item)?item.flat():item)))
}
function flatter(arr){
    let arrs = []
    arr.map(item => {
        if(Array.isArray(item){
            arrs.push(...flatter(item))
        }else {
            arrs.push(item)
        }
    })
    return arrs
}
/**
* 迭代实现
*/
function flatten(arr) {
    let arrs =[...arr]
    let newArr = [];
    while (arrs.length){
    let item = arrs.shift()
    if(Array.isArray(item)){
      arrs.unshift(...item)
    }else {
      newArr.push(item)
    }
    }
    return newArr
    }
[1,[2,3,[4,5]],8].join(',').split(',').map(item => Number(item));

实现new构造函数

  1. 创建了一个新对象(是Object类型的数据)
  2. 将this指向新对象
  3. 将创建的对象的原型指向构造函数的原型
  4. 返回一个对象(如果构造函数本身有返回值且是对象类型,就返回本身的返回值,如果没有才返回新对象)
function _new(fn,arg){
    const obj = Object.create(fn.prototype)
    const ret = fn.apply(obj,arg)
    return ret instanceof Object ? ret : obj
}
function _new(){
    const obj = Object.create(null)
    const Fn = [].shift.call(arguments)
    //通过apply将this指向由Fn变为obj
    const ret = Fn.apply(obj,arguments)
    // 3、将新对象的原型指向构造函数的原型
    obj.__proto__ = Fn.prototype
    return Object.prototype.call(ret) === '[object Object]' ? ret : obj
}

扁平数据转Tree

测试数据

const data =
   [
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:16',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 100,
      'pid': 0,
      'ancestors': '0',
      'deptName': '若依科技',
      'orderNum': '0',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:16',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 110,
      'pid': 0,
      'ancestors': '0',
      'deptName': '鸿星尔克',
      'orderNum': '0',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:16',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 101,
      'pid': 100,
      'ancestors': '0,100',
      'deptName': '深圳总公司',
      'orderNum': '1',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:16',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 102,
      'pid': 100,
      'ancestors': '0,100',
      'deptName': '长沙分公司',
      'orderNum': '2',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:16',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 103,
      'pid': 101,
      'ancestors': '0,100,101',
      'deptName': '研发部门',
      'orderNum': '1',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:17',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 104,
      'pid': 101,
      'ancestors': '0,100,101',
      'deptName': '市场部门',
      'orderNum': '2',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:17',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 105,
      'pid': 101,
      'ancestors': '0,100,101',
      'deptName': '测试部门',
      'orderNum': '3',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:17',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 106,
      'pid': 101,
      'ancestors': '0,100,101',
      'deptName': '财务部门',
      'orderNum': '4',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:17',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 107,
      'pid': 101,
      'ancestors': '0,100,101',
      'deptName': '运维部门',
      'orderNum': '5',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:17',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 108,
      'pid': 102,
      'ancestors': '0,100,102',
      'deptName': '市场部门',
      'orderNum': '1',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    },
    {
      'searchValue': null,
      'createBy': 'admin',
      'createTime': '2021-04-06 03:56:17',
      'updateBy': null,
      'updateTime': null,
      'remark': null,
      'params': {},
      'id': 109,
      'pid': 102,
      'ancestors': '0,100,102',
      'deptName': '财务部门',
      'orderNum': '2',
      'leader': '若依',
      'phone': '15888888888',
      'email': 'ry@qq.com',
      'status': '0',
      'delFlag': '0',
      'parentName': null
    }
  ]

方式1 参考

const buildTree = (itemArray, { id = 'id', parentId = 'parentId', children = 'children', topLevelId = '0' } = {}) => {
  const parentMap = new Map(); // 临时存储所有父级
  const topLevelResult = [];   // 存储顶层结果
  for(let item of itemArray) {
    if(!parentMap.has(item[id])) {
      item[children] = []
    } else {
      item[children] = parentMap.get(item[id])[children];
    }
	
    parentMap.set(item.id, item)
	
    if(!parentMap.has(item[parentId])) {
      parentMap.set(item[parentId], {
        [children]: []
      });
    }
    parentMap.get(item[parentId])[children].push(item)
    if (String(item[parentId]) === String(topLevelId)) {
      topLevelResult.push(item)
    }
  }
  return topLevelResult;
}

方式二 参考

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;
}

方式三

这种方式会直接修改原有的item,多执行几次有可能会出现错误的结果

function arrayToTree(items){
  const parentMap = {}
  const itemMap = {}
  const result = []
  for(const item of items){
    const {id,pid} = item;
    
    if(parentMap[id]){
      item.children = parentMap[id]
     }

    if(!itemMap[pid]){
      (parentMap[pid]||(parentMap[pid]=[])).push(item)
    }else{
      (itemMap[pid].children || (itemMap[pid].children=[])).push(item)
    }
    
    itemMap[id] = item
    if(item.pid === 0){
      result.push(item)
    }
  }
  return result
}

方式四

这种方式生成的对原有的item不会有影响,而且末端节点不会有空的children属性

function arrayToTree (list, parentId = 0, key = 'id', pkey = 'pid') {
  const parentMap = {}
  const itemMap = {}
  const result = []
  for (const item of list) {
    const { [key]: id, [pkey]: pid } = item
    if (parentMap[id]) {
      item.children = parentMap[id]
    }

    const copyitem = { ...item }
    if (!itemMap[pid]) {
      (parentMap[pid] || (parentMap[pid] = [])).push(copyitem)
    } else {
      (itemMap[pid].children || (itemMap[pid].children = [])).push(copyitem)
    }
    itemMap[id] = copyitem
    if (item[pkey] === parentId) {
      result.push(copyitem)
    }
  }
  return result
}

方式五

function listToTree2 (list, parentId = 0, key = 'id', pkey = 'pid') {
  const treeMap = {}
  const result = []
  for (const item of list) {
    const id = item[key]
    const pid = item[pkey]

    if (!treeMap[pid]) {
      treeMap[pid] = { children: [item] }
    } else {
      treeMap[pid].children.push(item)
    }

    if (!treeMap[id]) {
      item.children = []
      treeMap[id] = item
    }

    if (pid === parentId) {
      result.push(item)
    }
  }
  return result
}

export function listToTree3 (list, parentId = 0, key = 'id', pkey = 'pid') {
  const treeMap = {}
  const result = []
  for (const item of list) {
    const id = item[key]
    const pid = item[pkey]

    const copyItem = { ...item }
    if (!treeMap[pid]) {
      treeMap[pid] = { children: [copyItem] }
    } else {
      treeMap[pid].children.push(copyItem)
    }

    if (!treeMap[id]) {
      copyItem.children = []
      treeMap[id] = copyItem
    }

    if (pid === parentId) {
      result.push(copyItem)
    }
  }
  return result
}