js Object.defineProperty的使用

2019-07-25 22:10  2596人阅读  评论 (0)
let obj = {
  hello: "hello111",
  world: 123,
  user: {
    name: 'vue',
    age: 4,
    blog: {
      title: "blog1",
      content: 888
    }
  }
}

function watch(o, prefix = "") {
  let wv = {}
  for (let key in o) {
    if (o[key].constructor === Object) {
      wv[key] = watch(o[key], `${prefix}${key}.`)
    }
  }

  let w = {}
  for (let key in o) {
    Object.defineProperty(w, key, {
      get() {
        let val = o[key]
        if (val.constructor === Object) {
          return wv[key]
        } else {
          console.log(`get ${prefix}${key}: `, val)
          return val
        }
      },
      set(val) {
        o[key] = val
        console.log(`set ${prefix}${key}: `, val)
        if (val.constructor === Object) {
          wv[key] = watch(o[key], `${prefix}${key}.`)
        }  else {
          delete wv[key]
        }       
      },
      enumerable : true,
      configurable : true
    })
  }
  return w
}

console.log(JSON.stringify(obj, " ", 2))

obj = watch(obj)

console.log("===============")

console.log(obj.hello)
obj.hello = "hello222"
console.log(obj.hello)

console.log(obj.world)
obj.world = 456
console.log(obj.world)

console.log("===============")

console.log(obj.user.name)
obj.user.name = "vuex"
console.log(obj.user.name)

console.log(obj.user.age)
obj.user.age = 18
console.log(obj.user.age)

console.log("===============")

console.log(obj.user.blog.title)
obj.user.blog.title = "blog111"
console.log(obj.user.blog.title)

console.log(obj.user.blog.content)
obj.user.blog.content = 999
console.log(obj.user.blog.content)

console.log("===============")

console.log(obj.user.blog)
obj.user.blog = {title: "blog333", content: 999}
console.log(obj.user.blog)
console.log(obj.user.blog.title)
console.log(obj.user.blog.content)

console.log(obj.user.blog.title)
obj.user.blog.title = "blog111"
console.log(obj.user.blog.title)

console.log(obj.user.blog.content)
obj.user.blog.content = 999
console.log(obj.user.blog.content)
豫ICP备09035262号-1