JS常见手写代码汇总

一、 EventBus

class EventBus {
  private events: {
    [key]:{fn, isOnce}
  }

  constructor() {
    this.events = {}
  }
  
  on (type, fn, isOnce = false) {
    const events = this.events
    if (events[type] == null) {
      events[type] = []
    }
    events[type].push({ fn, isOnce})
  }

  once (type,fn) {
    this.on(type, fn, true)
  }

  off (type, fn) {
    if (!fn) {
      this.events[type] = []
    } else {
      const fnList = this.events[type]
      if (fnList) {
        this.events[type] = fnList.filter(item => item.fn != fn)
      }
    }
  }

  emit(type, ...args) {
    const fnList = this.events[type]
    if (fnList == null) return

    this.events[type] = fnList.filter(item => {
      const { fn, isOnce } = item
      fn(...args)

      if (!isOnce) return true
      return false
    })
  }
}

二、lazyman

class lazyman {
  private name
  private tasks = []

  constructor( name ) {
    this.name = name

    setTimeout(() => {
      this.next()
    })
  }

  private next() {
    const task = this.tasks.shift()
    if (task) task()
  }

  eat(food) {
    const task = () => {
      console.info(`${this.name} eat ${food}`)
      this.next()
    }
    this.tasks.push(task)
    return this
  }

  sleep (seconds) {
    const task = () => {
      console.info(`${this.name} 开始睡觉`)

      setTimeout(() => {

        console.info(`${this.name} 已经睡完了 ${seconds}s,开始执行下一个任务`)
        this.next()

      }, seconds * 1000)
    }
    this.tasks.push(task)

    return this
  }
}

三、LRU 最近最少使用

class LRUCache {
  private length
  private data = new Map()

  constructor(length) {
    if (length < 1) throw new Error(`invalid length`)
    this.length = length
  }

  set(key, value) {
    const data = this.data

    if (data.has(key)) {
      data.delete(key)
    }
    data.set(key,value)

    if (data.size > this.length) {
      //超出容量,删除 Map最老元素
      const delKey = data.keys().next().value
      data.delete(delKey)
    }
  }

  get(key) {
    const data = this.data

    if (!this.data.has(key)) return null

    const value = data.get(key)

    data.delete(key)
    data.set(key, value)

    return value
  }
 
}

四、数组扁平化

function flatten(arr) {
  let res = []

  arr.forEach(item => {
    res = res.concat(item)
  });

  return res
}

//数组深度扁平化

function flattenDeep(arr) {
  let res = []

  arr.forEach(item => {
    if (Array.isArray(item)) {
      const flatItem = flattenDeep(item)
      res = res.concat(flatItem)
    } else {
      res = res.concat(item)
    }
  })

  return res
}

五、获取数据类型

function getType(obj) {
  const originType = Object.prototype.toString.call(obj)
  const spaceIndex = originType.indexOf('')
  const type = originType.slice(spaceIndex + 1, -1)

  return type.toLowerCase()
}

六、深拷贝考虑到 Map Set WeakMap WeakSet等特殊类型

function CloneDeep(obj, map = new WeakMap()) {
  if (typeof obj !== 'object' || obj == null) return obj

  const objFromMap = map.get(obj)
  if (objFromMap) return objFromMap

  let target = {}
  map.set(obj, target)

  //枚举法
  if (obj instanceof Map) {
    target = new Map()
    obj.forEach((v,k) => {
      const v1 = CloneDeep(v,map)
      const k1 = CloneDeep(k,map)
      target.set(k1, v1)
    })
  }

  if (obj instanceof Set) {
    target = new Set()
    obj.forEach(v => {
      const v1 = CloneDeep(v,map)
      target.add(v1)
    })
  }

  if (obj instanceof Array) {
    target = obj.map(item => CloneDeep(item, map))
  }

  if (const key in obj) {
    const val = obj[key]
    const val1 = CloneDeep(val, map)
    target[key] = val1
  }

  return target

}

七、数组转树

/*
const arr = [
{ id: 1, name: ‘部门A’, parentId: 0 }, // 0 代表顶级节点,无父节点
{ id: 2, name: ‘部门B’, parentId: 1 },
{ id: 3, name: ‘部门C’, parentId: 1 },
{ id: 4, name: ‘部门D’, parentId: 2 },
{ id: 5, name: ‘部门E’, parentId: 2 },
{ id: 6, name: ‘部门F’, parentId: 3 },
]
*/

interface IArrayItem {
 id: number
 name: string
 parentId: number
}

interface ITreeNode {
 id: number
 name: string
 children?: ITreeNode[]
}

function convert(arr: IArrayItem[]): ITreeNode | null {
 const idToTreeNode: Map<number, ITreeNode> = new Map()

 let root = null

 arr.forEach(item => {
   const { id, name, parentId } = item
   const treeNode:ITreeNode = {id, name}
   idToTreeNode.set(id,treeNode)

   const parentNode = idToTreeNode.get(parentId)
   if(parentNode) {
     if (parentNode.children == null) parentNode.children = []
     parentNode.children.push(treeNode)
   }
   if (parentId === 0) root = treeNode
 })

 return root
}

八、树转数组

/*
//
const obj = {
id: 1,
name: ‘部门A’,
children: [
{
id: 2,
name: ‘部门B’,
children: [
{ id: 4, name: ‘部门D’ },
{ id: 5, name: ‘部门E’ }
]
},
{
id: 3,
name: ‘部门C’,
children: [
{ id: 6, name: ‘部门F’ }
]
}
]
}
*/

function convert1(root: ITreeNode): IArrayItem[] {
  const nodeToParent: Map<ITreeNode, ITreeNode> = new Map()

  const arr: IArrayItem[] = []

  const queue: ITreeNode[] = []
  queue.unshift(root)

  while (queue.length > 0) {
    const curNode = queue.pop()
    if (curNode == null) break

    const { id, name, children = []} = curNode

    const parentNode = nodeToParent.get(curNode)
    const parentId = parentNode?.id || 0
    const item = { id, name, parentId}
    arr.push(item)

    children.forEach(child => {
      nodeToParent.set(child,curNode)
      queue.unshift(child)
    })
  }


  return arr
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值