简单理解proxy

什么是Proxy?它有什么作用?
Proxy的MDN

据阮一峰文章介绍:Proxy可以理解成,在目标对象之前架设一层 “拦截”,当外界对该对象访问的时候,都必须经过这层拦截,而Proxy就充当了这种机制,类似于代理的含义,它可以对外界访问对象之前进行过滤和改写该对象。

在vue2.+中

我们知道在Vue2.xx中使用 Object.defineProperty()方法对该对象通过 递归+遍历的方式来实现对数据的监控的。但是当我们使用数组的方法或改变数组的下标是不能重新触发 Object.defineProperty中的set()方法的,因此就做不到实时响应了。所以使用Object.defineProperty 存在如下缺点`:

1.监听数组的方法不能触发Object.defineProperty方法中的set操作(如果要监听的到话,需要重新编写数组的方法)。
2.必须遍历每个对象的每个属性,如果对象嵌套很深的话,需要使用递归调用。

因此vue3.xx中之后就改用Proxy来更好的解决如上面的问题。在学习使用Proxy实现数据双向绑定之前,我们还是一步步来,先学习了Proxy基本知识点。

Proxy的基本语法

const obj = new Proxy(target, handler);

参数说明如下:

target: 被代理对象。

handler: 是一个对象,声明了代理target的一些操作。

但是当外界每次对obj进行操作时,就会执行handler对象上的一些方法。handler中常用的对象方法如下:

get(target, propKey, receiver)
set(target, propKey, value, receiver)
has(target, propKey)
如上是Proxy中handler 对象的方法,其实它和Reflect里面的方法类似的

const target = {
  name: 'artiely'
};

const handler = {
  get: function(target, key) {
    console.log(`${key} 被读取`);
    return target[key];
  },
  set: function(target, key, value) {
    console.log(`${key} 被设置为 ${value}`);
    target[key] = value;
  }
};

const testObj = new Proxy(target, handler);

/*
  获取testObj中name属性值
  会自动执行 get函数后 打印信息:name 被读取 
*/
console.log(testObj.name); // 输出名字 artiely

/*
 改变target中的name属性值
 打印信息如下: name 被设置为 111 
*/
testObj.name = 111;

console.log(target.name); // 输出 111
// 这里为什么会打印出一样的内容,因为testObj对于target的

如上代码所示:也就是说
target——>是被代理的对象
handler——>是代理target的

那么handler上面有set和get方法:
当每次打印target中的name属性值的时候会自动执行handler中get函数方法(可以理解为:get方法就是获取这个属性值的作用)
当每次设置 target.name 属性值的时候,会自动调用 handler中的set方法,
(可以理解为:set方法就是将改变的新值)
因此target对象对应的属性值会发生改变,同时改变后的 testObj对象也会发生改变。因为对象是引用类型,是同一个内存地址。
看下列代码:

const target = {
  name: 'artiely'
};

const testA = target;

testA.name = 'xxx';

console.log(testA.name); // 打印 xxx

console.log(target.name); // 打印 xxx

get(target, propKey, receiver)

该方法的含义是:用于拦截某个属性的读取操作。它有三个参数,如下解析:
target: 目标对象。

propKey: 目标对象的属性。

receiver:(可选),该参数为上下文this对象

如下代码演示:

const obj = {
  name: 'artiely'
};

const handler = {
  get: function(target, propKey) {
    // 使用 Reflect来判断该目标对象是否有该属性
    if (Reflect.has(target, propKey)) {
      // 使用Reflect 来读取该对象的属性
      return Reflect.get(target, propKey);
    } else {
      throw new ReferenceError('该目标对象没有该属性');
    }
  }
};

const testObj = new Proxy(obj, handler);

/* 
 Proxy中读取某个对象的属性值的话,
 就会使用get方法进行拦截,然后返回该值。
 */
console.log(testObj.name); // artiely

/*
 如果对象没有该属性的话,就会进入else语句,就会报错:
 Uncaught ReferenceError: 该目标对象没有该属性
*/
// console.log(testObj.name2);

/*
 其实Proxy中拦截的操作是在原型上的,因此我们也可以使用 Object.create(obj)
 来实现对象的继承的。
 如下代码演示:
*/
const testObj2 = Object.create(testObj);
console.log(testObj2.name);

// 看看他们的原型是否相等 
console.log(testObj2.__proto__ === testObj.__proto__);  // 返回true

set(target, propKey, value, receiver)
该方法是用来拦截某个属性的赋值操作,它可以接受四个参数,参数解析分别如下:
target: 目标对象。

propKey: 目标对象的属性名

value: 属性值

receiver(可选): 一般情况下是Proxy实列 如下代码演示:

const obj = {
  'name': 'artiely'
};

const handler = {
  set: function(obj, prop, value) {
    return Reflect.set(obj, prop, value);
  }
};

const proxy = new Proxy(obj, handler);

proxy.name = '我是artiely';

console.log(proxy.name); // 输出: 我是artiely
console.log(obj); // 输出: {name: '我是artiely'}

注意:proxy对数组也是可以监听的;如下代码演示,数组中的 push方法监听:

const obj = [{
  'name': 'artiely'
}];

const handler = {
  set: function(obj, prop, value) {
    return Reflect.set(obj, prop, value);
  }
};

const proxy = new Proxy(obj, handler);

proxy.push({'name': 'artiely222'});

proxy.forEach(function(item) {
  console.log(item.name); // 打印出 artiely artiely222
});

has(target, propKey)

该方法是判断某个目标对象是否有该属性名。接收二个参数,分别为目标对象和属性名。返回的是一个布尔型。 如下代码演示:

const obj = {
  'name': 'artiely'
};

const handler = {
  has: function(target, key) {
    if (Reflect.has(target, key)) {
      return true;
    } else {
      return false;
    }
  }
};

const proxy = new Proxy(obj, handler);

console.log(Reflect.has(obj, 'name')); // true
console.log(Reflect.has(obj, 'age')); // false

以上就是对与proxy的一些常用语法,如果想详细了解可以去MDN查看。

总结
1.Proxy是ES6新推出的一个特性,可以用它去拦截js操作的方法,从而对这些方法进行代理操作。
2.相比Object.defineProperty,proxy可以监听数组的变化,可以劫持整个对象,并返回一个新对象。
参考文章:掘金大佬的文章

原文链接:https://blog.csdn.net/weixin_42282727/article/details/109435483

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TypeScript 中的代理(Proxy)是一种机制,它允许你拦截并自定义对象的操作。通过使用代理,你可以在对象的属性访问、赋值、函数调用等操作之前或之后执行自定义逻辑。这为你提供了更大的灵活性和控制力。 要创建一个代理对象,你可以使用 `Proxy` 构造函数。它接受两个参数:目标对象和一个处理程序对象(也称为代理处理器)。代理处理程序是一个包含各种钩子方法的对象,用于拦截和处理不同的操作。 下面是一个简单的示例,演示如何使用 TypeScript 创建一个代理对象: ```typescript const target = { name: "John", age: 30 }; const handler = { get: function(target, prop) { console.log(`Getting property ${prop}`); return target[prop]; }, set: function(target, prop, value) { console.log(`Setting property ${prop} to ${value}`); target[prop] = value; } }; const proxy = new Proxy(target, handler); console.log(proxy.name); // 输出:Getting property name,John proxy.age = 35; // 输出:Setting property age to 35 console.log(proxy.age); // 输出:Getting property age,35 ``` 在上面的示例中,我们创建了一个名为 `target` 的普通对象,它具有 `name` 和 `age` 两个属性。然后,我们定义了一个代理处理程序 `handler`,其中包含了 `get` 和 `set` 两个钩子方法。在这些方法中,我们可以自定义对象的属性访问和赋值行为。最后,我们使用 `new Proxy` 创建了一个代理对象 `proxy`,并对其进行了一些操作。 注意:由于 TypeScript 是 JavaScript 的超集,上述示例中的代码也适用于 JavaScript 环境。 希望这个简单的示例能够帮助你理解 TypeScript 中的代理概念和用法。如果你有更多问题,请随时提出。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值