vue如何处理对象和数组

Object.defineProperty()

  • Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
  • 参数:
    - obj: 需要定义属性的对象
    - prop: 要定义或修改属性的名称或symbol
    - descriptor: 要定义或修改的属性描述符
  • 返回值:
  •   - 被传递给函数的对象
    

Object.setPrototypeOf()

  • Object.setPrototypeOf()方法设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null。
  • 参数:
    - obj: 要设置其原型的对象
    - prototype: 该对象的新原型(一个对象 或null)
// 判断是否是对象的方法
function isObject (target) {
  // 返回一个验证方法
  return typeof target === 'object' && null !== target
}

// 先要获取原有数组上的所有原型方法
let oldProto = Array.prototype
// 创建一个对象, 并且这个对象的原型是指向原有数组的所有原型方法
let protoMethods = Object.create(oldProto)
// 数组的7个方法
let methods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']
// 对这7个方法进行重写
methods.forEach(method => {
  protoMethods[method] = function (...args) {
    // args 是用户使用上述7个方法添加的参数
    // 特殊的三个方法: push, unshift, splice
    let inserted
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    observeArray(inserted)
    // 对原有的方法功能进行保留  apply 第二个参数传入的是数组
    oldProto[method].apply(this, args)
  }
})

// 专门拦截数组的处理
function observeArray(arr) {
  for(let i=0;i<arr.length;i++) {
    // 这里获取数组的每一项
    let item = arr[i]
    // 给数组的每一项,如果是对象的话, 添加拦截
    observe(item)

  }
}

function observe (target) {
  // 先判断是否是对象
  if (!isObject(target)) {
      return target
  }
  // 判断是否是数组
  if (Array.isArray(target)) {
    observeArray(target)
    // 这里对数组的 7 个方法进行重写
    // 我们需要指定target 与 protoMethods 的关系
    // target.__proto__ = protoMethods  老写法
    Object.setPrototypeOf(target, protoMethods)
  }else {
    // 然后在过滤 对对象添加拦截 对象的遍历
    Object.keys(target).forEach(key => {
      // 这里对对象进行拦截
      defineReactive(target, key, target[key])
    })
  }
}

// 处理对象 对对象进行拦截的方法
function defineReactive (obj, key, value) {
  // 需要判断下原值里面是否有对象
  observe(value)
  // 通过Object.defineProperty
  Object.defineProperty(obj, key, {
    get() {
      console.log('get')
      return value
      },

    set(newValue) {
      console.log('set')
      // 新的值和原值不相同时
      if (newValue !== value) {
        // 如果传递的新值是一个对象
        observe(newValue)
        // 将新值赋值给原值
        value = newValue
      }
    }
  })
}

let obj ={
  arr: [1,2,3,4, {d: 5}],
  name: 'zs',
  age: 18,
  a: {
    b: 100
  }
}
observe(obj)
//obj.name = 'ls'
//console.log(obj.name)
//console.log(obj.a)

//obj.name = {c: 200}
obj.arr.push(6)
obj.arr.splice(2, 0 ,8)
console.log(obj.arr)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值