Object.defineProperty() - VS - new Proxy()

目录

Object.defineProperty() 

new Proxy()

Object.defineProperty的缺陷

1. 无法检测到对象属性的新增或删除

2. 无法监听数组变化


Vue2.0 :
通过 Object.defineProperty 方法属性拦截的方式,把 data 对象里每个数据的读写转化成 getter/setter,当数据变化时通知视图更新。

Object.defineProperty() 

语法:

Object.defineProperty(obj, property, descriptor)

下面重点讲述第三个参数:descriptor:

在JS中对象具有两种属性,分别是数据属性和访问器属性,
所以其描述符也根据属性分类,分为数据描述符  和  访问器描述符 

在使用描述符时,必须是两种形式之一,且两者不能同时使用。
当使用了getter或setter方法,不允许使用writable和value
这两个属性(如果使用,会直接报错滴)

数据描述符
具有以下可选的键值:

configurable:表示该属性能否通过delete删除,能否修改属性的特性或者能否修改访问器属性,默认为false。
enumerable:表示该属性是否可以枚举,即可否通过for..in访问属性。默认为false。

value:表示该属性的值。可以是任何有效的JS值。默认为undefined。
writable:表示该属性的值是否可写,默认为false。

访问器描述符
具有以下可选的键值:

configurable:表示该属性能否通过delete删除,能否修改属性的特性或者能否修改访问器属性,默认为false。
enumerable表示该属性是否可以枚举,即可否通过for..in访问属性。默认为false。

get:在读取属性时调用的函数,默认值为undefined。
set:在写入属性时调用的函数,默认值为undefined。

 const user = {
    age: 18,
    wife: {
      name: 'xiao',
      age: 17
    }
  }

  var newName = 'wang'
  Object.defineProperty(user, 'name', {
    get () {
      console.log('get方法调用了')
      return newName
    },
    set (val) {
      console.log('set方法调用了')
      newName = val
    }
  })

  console.log(user.name)
  user.name = 'lao wang'
  console.log(user.name)

打印结果如下:

Object.defineProperty()详解 - 天天向上吧 - 博客园在园子里看到一篇讲解Object.defineProperty()的非常好的博文,我把他转载过来,给自己留个笔记。原文出处https://www.cnblogs.com/junjun-001/p/11https://www.cnblogs.com/ldq678/p/13854113.html

new Proxy()

new Proxy() 把目标对象变成代理对象


参数1: user ----->  target目标对象
参数2: handler --> 处理器对象,用来监视数据,及数据的操作

 const user = {
    name: 'wang',
    age: 18,
    wife: {
      name: 'xiao',
      age: 17
    }
  }

  const proxyUser = new Proxy(user, {
    get (target, property) { // 读取目标对象的某个属性值
      console.log('get方法调用了')
      return Reflect.get(target, property)
    },
    set (target, property, val) { // 修改/添加属性值
      console.log('set方法调用了')
      return Reflect.set(target, property, val)
    },
    deleteProperty(target, property) { // 删除目标对象的某个属性
      console.log('delete方法调用了')
      return Reflect.deleteProperty(target, property)
    }
  })

  // 通过代理对象:
  // 查---获取目标对象中的某个属性值
  console.log(proxyUser.name)
  // 改---更新目标对象中的某个属性值
  proxyUser.name = 'lao wang'
  console.log(user)
  // 增---向目标对象中添加一个新的属性值
  proxyUser.sex = 'male'
  console.log(user)
  // 删---删除目标对象的某个属性值
  delete proxyUser.name
  console.log(user)

打印结果如下:

Object.defineProperty的缺陷

const data = {
  name: '',
};

// 遍历对象,对其属性值进行劫持
Object.keys(data).forEach(function(key) {
  Object.defineProperty(data, key, {
    enumerable: true,
    configurable: true,
    get: function() {
    },
    set: function(newVal) {
      // 当属性值发生变化时我们可以进行额外操作
      console.log(`大家好,我系${newVal}`);
    },
  });
});

data.name = '渣渣辉';

虽然Object.defineProperty通过为属性设置getter/setter能够完成数据的响应式,但是它并不算是实现数据的响应式的完美方案,主要缺陷有:

1. 无法检测到对象属性的新增或删除(直接新增属性、删除属性,页面不会更新);
2. 无法监听数组变化(直接通过下标修改数组,界面不会自动更新。)

无法检测到对象属性的新增或删除

<p>{{obj}}</p>
<p>{{arr}}</p>

data(){
    return {
        obj:{
            a:2
        }
    }
},
mounted () {
    this.obj.b = 222
},
<!-- obj显示结果 -->
//obj:{ "a": 2 }

解决方法:

(1)增加属性:

this.obj = Object.assign({},this.obj, { b: 1, e: 2 })
this.obj = {...this.obj,...{ b: 3, e: 2 }}

this.$set(this.obj,'f',0) // 或 vue.set(this.obj,'f',0)

(2)删除属性:

this.$delete(obj, propertyName/index) // 或 vue.delete(obj, propertyName/index)


无法监听数组变化

<p>{{arr}}</p>

data(){
    return {
        arr:[1,2]
    }
},
mounted () {
    this.arr[0]= 3333
},
<!-- arr显示结果 -->
arr:[ 1, 2 ]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值