详解JavaScript中Proxy与Object.defineProperty的区别

 更新时间:2023年06月13日 10:34:47   作者:不叫猫先生  
Proxy和Object.defineProperty都是JavaScript中用于实现对象属性拦截和代理的机制,但它们在功能和应用方面有一些区别,本文通过代码示例详细介绍了二者的区别,感兴趣的朋友可以参考下

功能方面的区别:

Object.defineProperty:它是ES5引入的属性定义方法,通过直接定义对象属性的特性(如可枚举性、可写性等),可以拦截属性的读取、写入和删除操作。但它只能拦截对象的属性访问,对于对象的整体操作(如对整个对象的赋值或属性遍历)并不会被拦截

Proxy:它是ES6引入的代理机制,可以对整个对象进行代理,拦截对象的各种操作,包括属性访问、赋值、删除、函数调用等。通过在代理对象上定义各种"陷阱"(trap)方法,可以自定义拦截行为,实现更细粒度的对象操作控制。

比如:

Object.defineProperty对整个对象进行赋值,不会触发set拦截

const obj = {};
Object.defineProperty(obj, 'name', {
  get() {
    console.log('访问name属性');
    return 'John';
  },
  set(value) {
    console.log('设置name属性');
    obj._name = value;
  }
});
// 访问name属性,触发get拦截
console.log(obj.name); // 输出: "访问name属性" 和 "John"
// 设置name属性,触发set拦截
obj.name = 'Alice'; // 输出: "设置name属性"
// 对整个对象进行赋值,不会触发set拦截
obj = { age: 25 }; // 抛出TypeError: Assignment to constant variable.

输出如下图所示:

Object.defineProperty对整个对象进行遍历,不会触发get拦截

const obj = { name: 'John', age: 25 };
Object.defineProperty(obj, 'name', {
  get() {
    console.log('访问name属性');
    return 'Alice';
  }
});
for (const key in obj) {
  console.log(key); // 输出: "name" 和 "age"
}
console.log(obj.name); // 输出: "访问name属性" 和 "Alice"

输出结果如下:

Proxy自定义拦截行为

const user = {
  name: 'John',
  age: 25,
};
const protectedUser = new Proxy(user, {
  set(target, property, value) {
    if (property === 'age') {
      throw new Error('age属性不可被修改');
    }
    return Reflect.set(target, property, value);
  },
  deleteProperty(target, property) {
    if (property === 'name') {
      throw new Error('name属性不可被删除');
    }
    return Reflect.deleteProperty(target, property);
  },
});
console.log(protectedUser.name); // 输出: "John"
protectedUser.name = 'Alice'; // 不会抛出错误,属性赋值成功
console.log(protectedUser.name); // 输出: "Alice"
protectedUser.age = 30; // 抛出错误,无法修改age属性
delete protectedUser.name; // 抛出错误,无法删除name属性

Proxy的优缺点

优点:

  • 更全面的拦截能力:Proxy可以拦截对象的更多操作,包括对属性的读取、赋值、删除等,以及函数的调用等,提供了更细粒度的拦截控制。
  • 可变性控制:Proxy可以用于控制对象的可变性,例如可以禁止对某些属性进行赋值或删除,从而实现更严格的对象保护和约束。

缺点

  • 兼容性问题:Proxy是ES6引入的新特性,旧版本的JavaScript环境可能不支持Proxy,因此在一些特定的环境或需求下,使用Proxy可能会导致兼容性问题。
  • 性能开销:相比Object.defineProperty,Proxy的拦截机制更为复杂,因此在某些情况下可能会引入一定的性能开销。但对于大多数应用场景来说,这种开销可以忽略不计。

到此这篇关于详解JavaScript中Proxy与Object.defineProperty的区别的文章就介绍到这了,更多相关Proxy与Object.defineProperty区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript中最常用的10种代码简写技巧总结

    JavaScript中最常用的10种代码简写技巧总结

    这篇文章主要总结了JavaScript中最常用的10种代码简写技巧的相关资料,其中包括三元操作符、短路求值简写方式、声明变量简写方法、if存在条件简写方法及JavaScript循环简写方法等等,分别给出了详细的示例代码供大家参考,需要的朋友们下面来一起看看吧。
    2017-06-06
  • 微信小程序使用onreachBottom实现页面触底加载及分页效果

    微信小程序使用onreachBottom实现页面触底加载及分页效果

    小程序还没有使用pc端的那种分页格式,下面这篇文章主要给大家介绍了关于微信小程序使用onreachBottom实现页面触底加载及分页效果的相关资料,需要的朋友可以参考下
    2022-10-10
  • js select option对象小结

    js select option对象小结

    本篇文章主要是对js中的select option对象进行了总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12
  • url特殊字符编码encodeURI VS encodeURIComponent分析

    url特殊字符编码encodeURI VS encodeURIComponent分析

    这篇文章主要介绍了url特殊字符编码encodeURI VS encodeURIComponent分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • JavaScript 新手24条实用建议[TUTS+]

    JavaScript 新手24条实用建议[TUTS+]

    本文列出了24条能让你的代码编写过程更为轻松高效的建议。也许您还是JavaScript初学者,刚刚写完自己的Hello World,那这里有很多对您的工作将十分有用的小贴士;也许有些技巧您已经知道,那就试试快速浏览一下,看能不能发现一点新东西吧!
    2009-06-06
  • Bootstrap每天必学之模态框(Modal)插件

    Bootstrap每天必学之模态框(Modal)插件

    Bootstrap每天必学之模态框(Modal)插件,模态框(Modal)是覆盖在父窗体上的子窗体。通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动。子窗体可提供信息、交互等,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • JavaScript实现大图轮播效果

    JavaScript实现大图轮播效果

    这篇文章主要为大家详细介绍了JavaScript实现大图轮播效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • Js 控制表单域代码

    Js 控制表单域代码

    js改变下拉框的显示等实现代码。
    2009-05-05
  • JS实现从网页顶部掉下弹出层效果的方法

    JS实现从网页顶部掉下弹出层效果的方法

    这篇文章主要介绍了JS实现从网页顶部掉下弹出层效果的方法,实例分析了javascript创建弹出窗口及窗口掉落与抖动效果实现方法,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08

最新评论