javascript Object对象深层嵌套自动赋值

js中 给一个多层嵌套的object对象赋值需要十分小心, 一不小心就很容易出现undefined错误, 因为给一个object里深层对象赋值时, 需要确保整个object链路能够到达, 否则就会报undefined错误, 例如以下代码:

let a = {}
a.b.c.d = {}  // 会报错 因为链路无法到达d

常见的解决方法有

  1. 逐层判断赋值
let a = {}
if (!Object.prototype.hasOwnProperty.call(a, 'b')) {
  a.b = {}
}
if (!Object.prototype.hasOwnProperty.call(a.b, 'c')) {
  a.b.c = {}
}
...

缺点: 层数比较多的时候 代码会非常啰嗦

  1. 以key值链路数组递归赋值
let a = {}
let keys = ['b', 'c', 'd', 'e']
let temp = a
keys.forEach(key => {
  if (!Object.prototype.hasOwnProperty.call(temp, key)) {
    temp[key] = {}    
  }
  temp = temp[key]})
})

缺点: 需要把key链路变成数组 写起来会比较麻烦 因为常用的object用法是 a.b.c.d... 或者 a['b']['c']['d']... 转成数组 会额外增加心智开销

那么有没有一种方案, 可以实现

  1. 深层递归赋值

  2. 不影响原有的object的书写方式 原来的a.b.c.d... 或者 a['b']['c']['d']... 不需要修改

结合javascript的Proxy方法 形成如下方案:

class ObjectUtil {
  constructor (keys = []) {
    let obj = {}
    const fix = this.fix.bind(this)
    const value = this.value.bind(this)
    obj.fix = fix
    obj.value = value
    obj = new Proxy(
      obj,
      {
        get (target, p, receiver) {
          if (target[p] !== fix && target[p] !== value) {
            if (!Object.prototype.hasOwnProperty.call(target, p)) {
              const k = JSON.parse(JSON.stringify(keys))
              k.push(p)
              target[p] = new ObjectUtil(k)
            }
          }
          return Reflect.get(...arguments)
        }
      }
    )
    this._keys = keys
    return obj
  }

  fix (obj) {
    let a = obj
    for (const k of this._keys) {
      if (!Object.prototype.hasOwnProperty.call(a, k)) {
        a[k] = {}
      }
      a = a[k]
    }
    return a
  }

  value (obj) {
    let a = obj
    let value
    const keys = this._keys.reverse()
    for (let k = keys.pop(); k !== undefined; k = keys.pop()) {
      if (!Object.prototype.hasOwnProperty.call(a, k)) {
        break
      }
      if (keys.length === 0) {
        value = a[k]
      }
      a = a[k]
    }
    return value
  }
}

使用:

const a = {
  a: {},
  aa: {}
}

const temp = new ObjectUtil()
let c = temp.a.b.c.fix(a)
console.log(a)  // { a: { b: { c: {} } }, aa: {} }
let d = temp.a.b.d.fix(a)
console.log(a) // { a: { b: { c: {}, d: {} } }, aa: {} }

c,d = 1
let d = temp.a.b.c.d.value(a)
// d: 1
let e = temp.a.b.c.e.value(a)
// e: undefined

原理:

使用Proxy获取到object的key链路 比如obj.a.b.c.d key链路就是 a->b->c->d

new ObjectUtil() 会创建一个 Proxy对象

Proxy对象的get方法, 会获取到此对象的直属key, 然后判断目标对象在key上是否有value 如果没有 递归创建一个new ObjectUtil()

get (target, p, receiver) {
          if (target[p] !== fix && target[p] !== value) {
            if (!Object.prototype.hasOwnProperty.call(target, p)) {
              const k = JSON.parse(JSON.stringify(keys))
              k.push(p)
              target[p] = new ObjectUtil(k)
            }
          }
          return Reflect.get(...arguments)
        }

然后根据链路递归赋值

以上就是处理javascript Object对象深层嵌套自动赋值的一种思路, 如果有更好的方法, 可以留言讨论

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容