前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >js对象和类的操作

js对象和类的操作

作者头像
epoos
发布2022-06-06 16:09:00
2.3K0
发布2022-06-06 16:09:00
举报
文章被收录于专栏:epoos.com

1.对象深度优先遍历和广度优先遍历的实现

如图:

代码语言:javascript
复制
const obj = {
  a1: {
    a1b1: 1,
    a1b2: 2
  },
  a2: {
    a2b1: 3,
    a2b2: 4,
    a2b3: 5
  }
}
// 深度优先遍历
const depthArr = []
function depthFirst(obj) {
  for (let i in obj) {
    depthArr.push(i)
    if (Object.prototype.toString.call(obj[i]) === '[object Object]') {
      depthFirst(obj[i])
    }
  }
  return depthArr
}

// 广度优先遍历
const breadthArr = []
function breadthFirst(obj) {
  const arr = Object.keys(obj)
  breadthArr = breadthArr.concat(arr)
  arr.forEach(i => {
    if (Object.prototype.toString.call(obj[i]) === '[object Object]') {
      breadthFirst(obj[i])
    }
  })
}

depthFirst(obj) // ['a1', 'a1b1', 'a1b2', 'a2', 'a2b1', 'a2b2', 'a2b3']
breadthFirst(obj) // ['a1', 'a2', 'a1b1', 'a1b2', 'a2b1', 'a2b2', 'a2b3']
console.log(depthArr, breadthArr)

2.用深度优先思想实现一个深拷贝函数

深度拷贝最主要需要考虑的因素就是需要考虑js的各种数据类型 1)6种基本类型(number,string,null,undefined,boolean,symbol)不需要处理,直接复制返回即可 2)几种特殊类型 date、regexp、set、map,直接new一遍即可 3)需要着重处理的类型 Array、Object,直接使用递归处理即可 4)递归处理Array、Object的过程中需要考虑循环引用,循环引用处理可以利用WeakMap将每次递归的对象存储起来,如果一样,直接返回

代码语言:javascript
复制
const obj = {
  a1: {
    a1b1: 1,
    a1b2: 2
  },
  a2: {
    a2b1: 3,
    a2b2: 4,
    a2b3: 5
  },
  fn1: function() {
    console.log('fn1')
  },
  symbolData: Symbol('symbolData'),
  booleanData: false,
  date: new Date(),
  nullData: null,
  arrData: [1, 2, 3, { arr1: { a:1, b: 2 }, arr2: [] }],
  numberData: 1,
  strData: 'abc',
  regexData: new RegExp('abcdefg'),
  setData: new Set(),
  mapData: new Map(),
}
obj.obj = obj // 循环引用

function isType(target, type) {
  if (!type) {
    return Object.prototype.toString.call(target).slice(8, -1)
  }
  return Object.prototype.toString.call(target) === `[object ${type}]`
}
function depthFirstClone(obj, hash = new WeakMap()) {
  const oType = isType(obj)
  if (oType !== 'Object' && oType !== 'Array') return obj
  if (hash.has(obj)) return hash.get(obj)

  const newObj = oType === 'Array' ? [] : {}
  hash.set(obj, newObj)

  for (let i in obj) {
    if (
      typeof obj[i] === 'string' ||
      typeof obj[i] === 'number' ||
      typeof obj[i] === 'boolean' ||
      typeof obj[i] === 'symbol' ||
      obj[i] === undefined ||
      obj[i] === null
    ) {
      newObj[i] = obj[i]
      continue
    }
    if (isType(obj[i], 'Function')) {
      newObj[i] = obj[i]
      continue
    }
    if (isType(obj[i], 'Set')) {
      newObj[i] = new Set(obj[i])
      continue
    }
    if (isType(obj[i], 'Map')) {
      newObj[i] = new Map(obj[i])
      continue
    }
    if (isType(obj[i], 'Date')) {
      newObj[i] = new Date(obj[i])
      continue
    }
    if (isType(obj[i], 'RegExp')) {
      newObj[i] = new RegExp(obj[i])
      continue
    }
    if (isType(obj[i], 'Array') || isType(obj[i], 'Object')) {
      newObj[i] = depthFirstClone(obj[i], hash)
      continue
    }
  }
  return newObj
}
let cloneObj = depthFirstClone(obj)

3.实现一个LazyMan类,实现以下功能

代码语言:javascript
复制
LazyMan('Tony') // Hi I am Tony
LazyMan('Tony').sleep(10).eat('lunch') 
// Hi I am Tony 
// 等待10s
// I am eating lunch
LazyMan('Tony').eat('lunch').sleep(10).eat('dinner')
// Hi I am Tony 
// I am eating lunch
// 等待10s
// I am eating dinner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
// Hi I am Tony 
// 等待5s
// I am eating lunch
// I am eating dinner
// 等待10s
// I am eating junk food
代码语言:javascript
复制
class LazyManClass {
  constructor(name) {
    this.name = name
    this.task = []
    console.log(`Hi I am ${this.name}`)
    setTimeout(() => this.next())
  }
  sleepFirst(time) {
    const fn = () => {
      console.log(`sleep ${time}ms`)
      setTimeout(() => {
        this.next()
      }, time)
    }
    this.task.unshift(fn)
    return this
  }
  sleep(time) {
    const fn = () => {
      console.log(`sleep ${time}ms`)
      setTimeout(() => {
        this.next()
      }, time)
    }
    this.task.push(fn)
    return this
  }
  eat(food) {
    this.task.push(() => {
      console.log(`I am eating ${food}`)
      this.next()
    })
    return this
  }
  next() {
    const fn = this.task.shift()
    fn && fn()
  }
}
function LazyMan(name) {
  return new LazyManClass(name)
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5000).sleep(10000).eat('junk food')

4、定义一个列表类List,该类包含成员方法 add()、all() 和属性 length,要求构造函数和add0方法的参数为动态参数

代码语言:javascript
复制
// 构造函数示例:
var ls = new List('A', 'B','C')
// add方法示例
ls.add('D','E');
// length属性
ls.length; // =>5
// items属性
ls.all(); // =>【A,B,"C,"D,"E]
代码语言:javascript
复制
class List {
  constructor() {
    this.args = [...arguments]
  }
  add() {
    this.args = Array.prototype.concat(this.args, [...arguments])
  }
  all() {
    return this.args
  }
  get length() {
    return this.args.length
  }
}

let ls = new List('A', 'B', 'C')
ls.add('D', 'E')
console.log(ls.length)
ls.all()

5.实现convert方法,把原始list转换成树形结构,要求尽可能降低时间复杂度

以下数据结构中,id代表部门编号,name是部门名称,parentId是父部门编号,为0代表一级部门,现在要求实现一个convert方法,把原始list转换成树形结构,parantId为多少就挂载在该id的属性children数组下

代码语言:javascript
复制
let list = [
  { id: 1, name: '部门A', parentId: 0 },
  { id: 2, name: '部门B', parentId: 0 },
  { id: 3, name: '部门C', parentId: 1 },
  { id: 4, name: '部门D', parentId: 1 },
  { id: 5, name: '部门E', parentId: 2 },
  { id: 6, name: '部门F', parentId: 3 },
  { id: 7, name: '部门G', parentId: 2 },
  { id: 8, name: '部门H', parentId: 4 },
  // ...
]
function convert(list) {
  const res = []
  const map = {}
  list.forEach(item => map[item.id] = item)
  list.forEach(item => {
    if (item.parentId === 0) return res.push(item)
    const parent = map[item.parentId]
    if (parent.children) {
      parent.children.push(item)
    } else {
      parent.children = [item]
    }
  })
  return res
}

let result = convert(list)
result = [{
  id: 1,
  name: '部门A',
  parentId: 0,
  children: [{
    id: 3,
    name: '部门3',
    parentId: 1,
    children: [{
      id: 6,
      name: '部门6',
      parentId: 3,
    }]
  }]
}, /* ... */]

6.将entry转换为output、将output转换为entry:

代码语言:javascript
复制
var entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae',
}
// =>
var output = {
  a: {
    b: {
      c: {
        dd: 'abcdd'
      }
    },
    d: {
      xx: 'adxx'
    },
    e: 'ae'
  }
}
代码语言:javascript
复制
// entry => output
function gen(obj = {}, str, val) {
  str.split('.').reduce((acc, i, idx, source) => {
    if (!acc[i]) {
      acc[i] = idx === source.length - 1 ? val : {}
    }
    return acc[i]
  }, obj)
  return obj
}
function generater(obj) {
  const newObj = {}
  for (let i in obj) {
    gen(newObj, i, obj[i])
  }
  return newObj
}
generater(entry)
代码语言:javascript
复制
// output => entry answer1
const isObj = val => Object.prototype.toString.call(val) === '[object Object]'
function fn(obj = {}, key, newObj = {}) {
  for (let i in obj) {
    const nkey = key ? key + '.' + i : i
    if (isObj(obj[i])) {
      fn(obj[i], nkey, newObj)
    } else {
      newObj[nkey] = obj[i]
    }
  }
  return newObj
}
// output => entry answer2
function fn(obj = {}) {
  const queue = Object.entries(obj)
  const res = {}
  while(queue.length) {
    const [key, obj] = queue.pop()
    for (const [k, v] of Object.entries(obj)) {
      if (!isObj(v)) {
        res[`${key}.${k}`] = v
      } else {
        queue.push([`${key}.${k}`, v])
      }
    }
  }
  return res
}

7.实现一个简单的仓储系统,可以不断转入和转出货物,货物最多有两层子类目,数字代表该子类目转入/转出的数量。转出时不能出现爆仓情况。

代码语言:javascript
复制
/*
 * cargo 说明:
 * key代表类目/子类目名称
 * value 为 number时,代表这个类目的数量,为object 时,代表下一层货物的集合,最多嵌套两层
 * {
 *  productA:{  // 代表货物的类目名称
 *    a:1, // 1 代表子类目 a 的数量
 *    b:2,
 *    c:{   // c 代表货物的子类名称
 *      c1:1, // c1代表货物的子类名称
 *    }
 *   },
 *  productB:{
 *      e:6
 *   }
 * }
 *
 * 爆仓情况:如转入 {productA:{a:3,c:1}} 转出 {productA:{a:4}},就会发生子类目a爆仓,此时要返回报错。
 */

class Depository {
  constructor() {
    this.product = {}
  }
  compineProduct(cargo, product) {
    for (let i in cargo) {
      if (!product[i]) {
        product[i] = {}
      }
      if (typeof cargo[i] === 'number') {
        if (typeof product[i] === 'number') {
          product[i] += cargo[i]
        } else {
          product[i] = cargo[i]
        }
      } else {
        this.compineProduct(cargo[i], product[i])
      }
    }
  }
  reduceProduct(cargo, product) {
    for (let i in cargo) {
      if (!product[i]) {
        throw `货物${i}不存在`
      }
      if (typeof cargo[i] === 'number') {
        if (product[i] - cargo[i] <= 0) {
          throw `货物${i}爆仓`
        }
        product[i] -= cargo[i]
      } else {
        this.reduceProduct(cargo[i], product[i])
      }
    }
  }
  // 转入货物
  transferIn(cargo) {
    if (!cargo) return this.product
    this.compineProduct(cargo, this.product)
    return this.product
  }
  // 转出货物
  transferOut(cargo) {
    if (!cargo) return this.product
    this.reduceProduct(cargo, this.product)
    return this.product
  }
}

8.使用Javascript Proxy实现简单的数据绑定

代码语言:javascript
复制
<input id="inputField" value="" type="text" placeholder="" />
<p id="showField"></p>
代码语言:javascript
复制
const proxy1 = {
  get(target, propKey) {
    console.log(`getting:${propKey}`)
    return Reflect.get(target, propKey)
  },
  set(target, propKey, value) {
    console.log(`setting:${propKey}、${value}`)
    handler(value)
    return Reflect.set(target, propKey, value)
  }
}

function handler(value) {
  document.querySelector('#showField').innerHTML = value
}

var obj = new Proxy({}, proxy1)
document.querySelector('#inputField').addEventListener('input', (e) => {
  obj.txt = e.target.value
})

demo

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.对象深度优先遍历和广度优先遍历的实现
  • 2.用深度优先思想实现一个深拷贝函数
  • 3.实现一个LazyMan类,实现以下功能
  • 4、定义一个列表类List,该类包含成员方法 add()、all() 和属性 length,要求构造函数和add0方法的参数为动态参数
  • 5.实现convert方法,把原始list转换成树形结构,要求尽可能降低时间复杂度
  • 6.将entry转换为output、将output转换为entry:
  • 7.实现一个简单的仓储系统,可以不断转入和转出货物,货物最多有两层子类目,数字代表该子类目转入/转出的数量。转出时不能出现爆仓情况。
  • 8.使用Javascript Proxy实现简单的数据绑定
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档