JavaScript的es6新增Proxy/Reflect ,你知道吗?

之前学了vue3课程(vue3的响应式原理使用的就是Proxy),课程中老师经常提到proxy、响应式原理等,感觉很难很高深。现在学了,才真正了解。

一、Proxy类(代理)

        监听一个对象的相关操作,比如对象添加、删除、修改属性等。通过捕获器监听对象的改变。

        在es6直接如果想要监听对象的改变,需要使用Object.defineProperty()进行监听。代码如下:

1.Object.defineProperty()监听对象改变

const obj = {name:'wgy',age:18}
Object.defineProperty(obj,'name',{
    get:function(){
        console.log('name属性被访问了')
    },
    set:function(newVal){
        console.log('name属性被设置了',newVal)
    }
})
console.log(obj.name)
obj.name = 'kobo'

2.Object.defineProperty()的缺点

  • 比如新增属性、删除属性,defineProperty监听不到

  • defineProperty的设计初衷是定义普通的属性,不是为了去监听一个对象中的所有属性

3.Proxy监听对象改变

const obj = { name: "wgy", age: 18 };

const objProxy = new Proxy(obj, {
  // 获取值时的捕获器  target-obj,key-name
  get(target, key, receiver) {
    console.log("值被获取了", target, key);
    return target[key];
  },
  // 设置值时的捕获器
  set(target, key, newValue, receiver) {
    console.log("值被设置了", newValue);
    target[key] = newValue;
  },
  // 监听in的捕获器
  has(target, key) {
    console.log("对象执行了in操作");
    return key in target;
  },
  // 监听delete的捕获器
  deleteProperty(target, key) {
    console.log("对象执行了delete操作");
    delete target[key];
  },
});

console.log(objProxy.name);
objProxy.name = "3333";
console.log(obj);
console.log("name" in objProxy);
delete objProxy.name;

  4. 其他捕获器

  • getPrototype()

    • Object.getPrototypeof() 获取对象的原型

  • setPrototype()

    • Object.setPrototypeof() 设置对象的原型

  • isExtensible()

    • Object.isExtensible() 判断对象是否可以添加属性

  • preventExtensions()

    • Object.preventExtensions() 阻止对象添加属性

  • getOwnPrototyDescriptor()

    • Object.getOwnPrototyDescriptor() 获取对象的属性描述符

  • defineProperty()

    • Object.defineProperty() 给对象添加属性描述符

  • ownKeys()

    • Object.getOwnPrototyNames()

    • Object.getOwnPrototySymbols()

  • apply() 用于函数对象

    • 监听函数调用操作

  • construct 用于函数对象

    • 监听new 操作符

//apply()和construct()捕获器用于函数对象,使用方法
function foo() {
  console.log(foo);
}
const fooProxy = new Proxy(foo, {
  apply(target, thisAry, argArray) {
    console.log("函数被调用了", thisAry, argArray);
    target.apply(thisAry, argArray);
  },
  construct(target, argArray, newTarget) {
    console.log("函数使用new");
    return new target(...argArray);
  },
});
fooProxy();
fooProxy.apply({}, [1, 4, 6]);
new fooProxy();

5.Proxy的receiver参数的使用

      修改this指向,是代理有意义。

const obj = {
  _name: "www",
  get name() {
    console.log(this);
    return this._name; //this指向obj
  },
  set name(newVal) {
    this._name = newVal;
  },
};

const objProxy = new Proxy(obj, {
  get(target, key, receiver) {
    // receiver是代理对象objProxy
    console.log("属性被获取了", key, receiver === objProxy);
    return Reflect.get(target, key, receiver);
    // 传入receiver,会把this改为代理对象receiver
  },
  set(target, key, newVal, receiver) {
    console.log("属性被设置了");
    Reflect.set(target, key, newVal, receiver);
  },
});

console.log(objProxy.name); //访问的是obj的get name
objProxy.name = "333333";

二、Reflect对象(映射)

     Reflect对象提供了很多操作js对象的方法,比如增删改等。与Object提供的方法类似。

     一般与Proxy配合使用。

const obj = { name: "www", age: 22 };

const objProxy = new Proxy(obj, {
  get(target, key) {
    // return target[key]
    return Reflect.get(target, key);
  },
  set(target, key, newValue) {
    // target[key] = newValue;
    let res = Reflect.set(target, key, newValue);
    console.log(res);//会返回设置结果
  },
});

console.log(objProxy);
objProxy.name = "hhh";

1.为什么会需要Reflect

  • 早期的ECMA规范中没有考虑到对对象本地操作如何设计会更规范,所以将这些方法API放到了Object上

  • Object作为一个构造函数,这些放到他身上不合适

  • 还包含一下类似于in、delete操作符,让js看起来有点奇怪

2.与Object方法的区别

可参考比较 Reflect 和 Object 方法 - JavaScript | MDN

3.Reflect的方法

  • Reflect.apply()

    • 对一个函数进行调用操作,同时可以传入一个数组作为调用参数。

  • Reflect.construct(target, argumentsList[, newTarget])

    • 对构造函数进行new操作

  • Reflect.defineProperty(target, propertyKey, attributes)

    • Object.defineProperty()

  • Reflect.deleteProperty(target, propertyKey)

    • Object.preventExtensions() 阻止对象添加属性

  • Reflect.get(target, propertyKey[, receiver])

    •  获取对象的属性

  • Reflect.getOwnPropertyDescriptor(target, propertyKey)

    • Object.getOwnPropertyDescriptor()

  • Reflect.getPrototypeOf(target)

    • Object.getPrototypeOf()

  • Reflect.has(target, propertyKey)

    • Object.isExtensible()

  • Reflect.ownKeys(target)

    • Object.keys()

  •  Reflect.preventExtensions(target)

    •  Object.preventExtensions()

  •  Reflect.set(target, propertyKey, value[, receiver])

    •  设置对象属性

  •  Reflect.setPrototypeOf(target, prototype)

    •  设置对象的原型

4.Reflect.construct()的使用

const stu = new Student("ww", 32);
console.log(stu);
console.log(stu.__proto__ === Student.prototype);

// 执行Student函数,创建出来的对象是Teacher对象
const tea = Reflect.construct(Student, ["wwww", 22], Teacher);
console.log(tea);
console.log(tea.__proto__ === Teacher.prototype);

参考:Reflect - JavaScript | MDN 

参考:深入JavaScript高级语法-coderwhy大神新课-学习视频教程-腾讯课堂

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
你好!关于"vue3proxy结合reflect"的问题,我理解你可能想了解如何在Vue 3中使用ProxyReflect结合起来。Vue 3是一个流行的JavaScript框架,而ProxyReflect则是ES6新增的特性。 在Vue 3中,可以使用Proxy对象来代理Vue实例,以便捕获对数据的访问和修改。Proxy对象可以拦截并处理对Vue实例的操作,比如读取、设置和删除属性等。而Reflect对象提供了一组用于操作对象的方法,比如Reflect.get()、Reflect.set()和Reflect.deleteProperty()等。 结合使用ProxyReflect可以提供更灵活的控制和监控能力。你可以通过在Vue实例上创建一个代理对象,来拦截对数据的访问和修改,并在代理处理器中使用Reflect方法来操作实际的数据。这样可以轻松地实现对数据的拦截、校验、代理等功能。 下面是一个简单的示例代码,展示了如何在Vue 3中使用ProxyReflect结合起来: ```javascript const data = { message: 'Hello, Vue!', }; const proxy = new Proxy(data, { get(target, key) { console.log('Getting ' + key); return Reflect.get(target, key); }, set(target, key, value) { console.log('Setting ' + key + ' to ' + value); return Reflect.set(target, key, value); }, }); // 创建Vue应用 const app = Vue.createApp({ data() { return proxy; // 使用代理对象 }, }); app.mount('#app'); ``` 在上面的代码中,我们创建了一个名为data的普通对象,并使用Proxy对象创建了一个代理对象proxy。在代理对象的get和set处理器中,我们分别使用Reflect.get和Reflect.set来操作实际的数据。这样,当我们通过Vue实例访问或修改数据时,会触发代理处理器,并通过Reflect方法操作实际的数据。 希望这个例子能帮助到你,如果还有其他问题,请随时提问!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值