Object.defineProperty 和 new Proxy

Object.defineProperty 和 new Proxy 都是 JavaScript 中用于对对象进行拦截和处理的机制,但它们有不同的优缺点。

Object.defineProperty 是一个用于定义或修改对象属性的方法。它可以通过设置属性的配置对象来实现对属性的拦截和修改。它的优点是它是原生的 JavaScript 方法,因此在所有支持 JavaScript 的环境中都可以使用。它可以用来实现属性值的访问控制、属性的计算和依赖追踪等功能。然而,它的缺点是它只能拦截对对象属性的直接访问,不能拦截对对象方法的调用,也不能拦截数组的操作。
Object.defineProperty 的设计初衷,并不是为了监听劫持一个对象中所有属性的

new Proxy 是 ES6 中引入的一个用于创建代理对象的构造函数。代理对象可以拦截并重定义基础对象的操作。它的优点是它可以拦截更多类型的操作,包括属性的读取、写入、删除、方法调用和构造函数调用等。它还提供了一些附加功能,如陷阱函数和代理行为控制。然而,它的缺点是它只能在支持 ES6 的环境中使用,并且在某些情况下可能会导致性能下降。

Object.defineProperty

const obj = {};
Object.defineProperty(obj, 'name', {
  value: 'John',
  writable: false,
  enumerable: true,
  configurable: true
});
console.log(obj.name); // 输出 "John"
obj.name = 'Jane'; // 由于 writable 属性被设置为 false,赋值操作无效
console.log(obj.name); // 输出 "John"
let obj10 = {};
  Object.defineProperty(obj10, 'name', {
    get: function () {
      return this.value;
    },
    set: function (newVal) {  //设置值(说明有数据更新)
      this.value = newVal;
    }
  });
  console.log(obj10.name); // undefined
  obj10.name = '李四'; // 给obj.name赋新值
  console.log(obj10.name); // 李四

如果一个描述符同时拥有 value 或 writable 和 get 或 set 键,则会产生一个异常测试代码:

var obj = {}
// value和 get 只能同时用一个
Object.defineProperty(obj, 'name', {
	value: '孙悟空',
	get: function() {
		console.log('get')
		return this.value
	}
})
// writable和set只能同时用一个
Object.defineProperty(obj, 'name', {
	writable: true,
	set: function(newValue) {
		console.log('set')
	}
})

Proxy
基本语法如下:

/*
 * target: 目标对象
 * handler: 配置对象,用来定义拦截的行为
 * proxy: Proxy构造器的实例
 */
var proxy = new Proxy(target,handler)

Proxy也只代理外面一层属性,需要递归代理属性嵌套的对象属性

let obj = {a: 3, b: { c: 3 }};
let handler = {
  get:function(obj, prop){
    const v = Reflect.get(obj, prop);
    return v; // 返回obj[prop]
  },
  set(obj, prop, value){
    return Reflect.set(obj, prop, value); // 设置成功返回true
  }
};
let p=new Proxy(obj,handler);
p.a//会触发get方法

let obj = {a: 3, b: { c: 3 }};
let handler = {
  get:function(obj, prop){
    const v = Reflect.get(obj, prop);
    if(v !== null && typeof v === 'object'){
      return new Proxy(v,handler);//代理内层
    }else{
      return v; // 返回obj[prop]
    }
  },
  set(obj, prop, value){
    return Reflect.set(obj, prop, value);//设置成功返回true
  }
};
let p=new Proxy(obj,handler);
 
p.a//会触发get方法
p.b.c//会先触发get方法获取p.b,然后触发返回的新代理对象的.c的set。

什么样的 num 可以满足 (num === 1 && num === 2 && num === 3) === true 呢?(注意是 3 个 =,也就是严格相等)
解决:每次访问 num 返回的值都不一样,那么肯定会想到数据劫持

let current = 0;
Object.defineProperty(window, 'num', {
  get () {
    current++
    console.log(current)
    return current
  }
})
console.log(num === 1 && num === 2 && num === 3) // true

总结

1、Proxy 是对整个对象的代理,而 Object.defineProperty 只能代理某个属性
2、对象上新增属性,Proxy 可以监听到,Object.defineProperty 不能
3、数组新增修改,Proxy 可以监听到,Object.defineProperty 不能
4、若对象内部属性要全部递归代理,Proxy 可以只在调用的时候递归,而 Object.definePropery 需要一次完成所有递归,性能比 Proxy 差
5、Proxy 不兼容 IE,Object.defineProperty 不兼容 IE8 及以下

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值