vue中的defineProperty与proxy

目录

defineProperty

**obj.defineProperty的工作原理:

 **vue2是如何使用obj.defineProperty

proxy


defineProperty:

众所周知,vue2是通过obj.defineProperty来实现数据劫持的。那么obj.defineProperty是如何来工作以及vue2是如何追踪数据变化的呢?

**obj.defineProperty的工作原理:

obj.defineProperty是ES5提供的一个静态方法,用来直接在一个对象上定义一个新的属性,或者修改其新的属性并将其返回,使用方法:

obj.defineProperty(obj,prop,descriptor)

*obj:目标对象

*prop:一个字符串或 Symbol,指定了要定义或修改的属性键

*descriptor:要定义或修改的属性的描述符

configurable

(公用)

是否可以修改默认属性,默认为false

enumerable

(公用)

是否可以被枚举,默认为false

writable

(数据描述符)

是否可以修改这个属性的值,默认为false

value

(数据描述符)

初始值。可以是任何有效的 JavaScript 值(数字、对象、函数等)默认为undefined

get

(访问描述符)

 用作属性 getter 的函数,如果没有 getter 则为 undefined。当访问该属性时,将不带参地调用此函数,并将 this 设置为通过该属性访问的对象(因为可能存在继承关系,这可能不是定义该属性的对象)。返回值将被用作该属性的值。默认值为undefined

set

(访问描述符)

用作属性 setter 的函数,如果没有 setter 则为 undefined。当该属性被赋值时,将调用此函数,并带有一个参数(要赋给该属性的值),并将 this 设置为通过该属性分配的对象。默认值为undefined

        

对象中存在的属性描述符主要有两种类型:数据描述符和访问器描述符。数据描述符是一个具有可写或不可写值得属性;访问描述符是由 getter/setter 函数对描述的属性。两种描述符只能去其一。

使用示例:

// 数据描述符 
let obj = {
    name: "小明"
  }
  Object.defineProperty(obj,'age',{
    configurable: true, //是否可以被delete
    enumerable: true, //是否可以被for in枚举或者使用Object.keys()获取到,
    writable: true, //定义是否可以被修改,
    value: 100
  })
  console.log("增加属性===",obj.age) //增加属性=== 100
  Object.defineProperty(obj,'name',{
    configurable: true, //是否可以被delete
    enumerable: true, //是否可以被for in枚举或者使用Object.keys()获取到,
    writable: true, //定义是否可以被修改,
    value: "小李"
  })
  console.log("修改属性===",obj.name) //修改属性=== 小李

//访问描述符
let tmp = '测试'
  // 访问器描述符
  Object.defineProperty(obj,'child', {
    configurable: true,
    enumerable: true,
    set(value) {
      console.log("set---")
      tmp = value
    },
    get() {
      console.log("get---")
      return tmp
    }
  })
  console.log("访问描述符==get",obj.child) //get---   访问描述符== 测试
  obj.child = "小花"
  console.log("访问描述符==set",obj.child)
  //set---
  //get---
  //访问描述符==set 小花

至于为神魔 obj.defineProperty不能监听数组和对象,可以参考

https://blog.csdn.net/XH_jing/article/details/120413904

总结一下:监听数组或者对象变化,想能消耗过大,所以在2.0这个方案被放弃了

 **vue2是如何使用obj.defineProperty

当把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用obj.defineProperty把这些 property 全部转为 ​​​​​​getter/setter,从而在内部让vue能够追踪依赖,在 property 被访问和修改时通知变更。

proxy:

随着vue3的出现,vue的深度响应由obj.defineProperty改为了proxy,proxy又是什么呢

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)

let p = new Proxy(target, handler);

*target:要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)

*handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为

猜你喜欢

转载自blog.csdn.net/qq_41687299/article/details/131652457