前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【揭秘Vue核心】深入解析Object.defineProperty和Proxy的区别,让你秒懂!

【揭秘Vue核心】深入解析Object.defineProperty和Proxy的区别,让你秒懂!

作者头像
奋飛
发布2023-07-10 11:41:08
5160
发布2023-07-10 11:41:08
举报
文章被收录于专栏:Super 前端

问题:Object.difinePropertyproxy 有什么区别?

Object.definePropertyProxy 是用于实现响应式数据的两种不同方式。

Object.defineProperty

Object.defineProperty 通过直接修改对象的属性描述符来实现数据的劫持。Vue 2.x 中就是通过 Object.defineProperty 来实现数据的响应式。但是 Object.defineProperty 有一些限制,比如只能劫持已经存在的属性,无法对新增属性或删除属性进行劫持。这就导致 Vue 2.x 需要在创建实例之前声明数据属性,否则无法实现响应式。

代码语言:javascript
复制
Object.defineProperty(obj, prop, descriptor)

属性

类型

描述

value

任意类型

设置属性的值。

writable

布尔值

指定属性是否可写。默认为 false,即属性是只读的。

enumerable

布尔值

指定属性是否可枚举。默认为 false,即属性不会出现在 for…in 循环和 Object.keys() 中。

configurable

布尔值

指定属性是否可配置。默认为 false,即不可删除并且禁止修改属性的特性(writable、enumerable 和 configurable)。

get

函数类型

获取属性值的函数。

set

函数类型

设置属性值的函数。

示例:

代码语言:javascript
复制
let obj = {}
Object.defineProperty(obj, "b", {
  get() {
    return bValue;
  },
  set(newValue) {
    bValue = newValue;
  },
  enumerable: true,
  configurable: true,
});
proxy

而 Vue 3.0 使用了 Proxy,它是 ES6 新增的特性。**Proxy 可以对整个对象进行劫持,包括对新增属性和删除属性的劫持。**它提供了一种编程范式的改变,可以更加灵活地监听和代理对象的操作。

代码语言:javascript
复制
const p = new Proxy(target, handler)

方法

作用

get(target, prop, receiver)

拦截对目标对象属性的读取操作,并返回相应的值。

set(target, prop, value, receiver)

拦截对目标对象属性的写入操作,并进行相应的处理。

has(target, prop)

拦截对 in 操作符的操作,判断属性是否存在于目标对象中。

deleteProperty(target, prop)

拦截对 delete 操作符的操作,删除目标对象的指定属性。

apply(target, thisArg, arguments)

拦截函数的调用操作,并进行相应的处理。

construct(target, arguments, newTarget)

拦截对目标对象使用 new 操作符创建实例的操作,并进行相应的处理。

getPrototypeOf(target)

拦截对目标对象的原型的读取操作,并返回相应的值。

setPrototypeOf(target, proto)

拦截对目标对象的原型的写入操作,并进行相应的处理。

isExtensible(target)

拦截对目标对象是否可扩展的判断操作。

preventExtensions(target)

拦截对目标对象添加新属性的操作,并进行相应的处理。

getOwnPropertyDescriptor(target, prop)

拦截对目标对象属性描述符的读取操作,并返回相应的属性描述符。

defineProperty(target, prop, descriptor)

拦截对目标对象属性描述符的写入操作,并进行相应的处理。

ownKeys(target)

拦截对 Object.getOwnPropertyNames 和 Object.getOwnPropertySymbols 的操作,返回目标对象所有自身属性的键名。

enumerate(target)

拦截对 for…in 循环的操作,返回目标对象所有可枚举的属性名。

通过在 handler 中实现这些方法,我们可以自定义拦截操作的行为,并对底层的对象进行劫持和改变。这使得我们能够更灵活地操作和控制对象的访问、修改和行为。

示例:

代码语言:javascript
复制
onst handler = {
    get: function(obj, prop) {
        return prop in obj ? obj[prop] : 37;
    }
};

const p = new Proxy({}, handler);
对比

Proxy 相比于 Object.defineProperty 的优势:

  • Proxy 可以代理整个对象,而不是单个属性,可以实现更细粒度的拦截和操作。
  • Proxy 可以监听新增属性和删除属性的操作,不需要事先声明属性。

Object.defineProperty 相比于 Proxy 的·优势:

  • Object.defineProperty 支持 IE9+ 浏览器
  • 可处理原始类型的相应,vue3中的 ref
延伸

vue3 中,响应式分引用类型、原始类型。

  • reactive() 仅对引用类型有效,原始类型无效 – 因为 JavaScript 没有可以作用于所有值类型的 “引用” 机制;
  • ref()方法来允许我们创建可以使用任何值类型的响应式,传入参数的值包装为一个带 .value 属性的 ref 对象。

Vue 的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该响应式对象的相同引用。

注意:替换一个响应式对象(引用地址 => 原始类型),也需要使用 ref

代码语言:javascript
复制
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key)
      return target[key]
    },
    set(target, key, value) {
      target[key] = value
      trigger(target, key)
    }
  })
}

function ref(value) {
  const refObject = {
    get value() {
      track(refObject, 'value')
      return value
    },
    set value(newValue) {
      value = newValue
      trigger(refObject, 'value')
    }
  }
  return refObject
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Object.defineProperty
  • proxy
  • 对比
  • 延伸
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档