ES6. proxy

ES6的Proxy提供了强大的对象代理能力,能够拦截并控制对象的访问,包括但不限于读取、设置属性,以及实现私有变量。相较于defineProperty,Proxy可以重定义更多操作,如in、delete及函数调用等,极大地增强了对象行为的定制化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. proxy

参考文献:https://www.jianshu.com/p/c2a1aa2e2b14

1.1作用

proxy在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作,必须通过这层拦截

var target = {
   name: 'poetries'
 };
 var logHandler = {
   get: function(target, key) {
     console.log(`${key} 被读取`);
     return target[key];
   },
   set: function(target, key, value) {
     console.log(`${key} 被设置为 ${value}`);
     target[key] = value;
   }
 }
 var targetWithLog = new Proxy(target, logHandler);
 
 targetWithLog.name; // 控制台输出:name 被读取
 targetWithLog.name = 'others'; // 控制台输出:name 被设置为 others
 
 console.log(target.name); // 控制台输出: others

对于代理模式 Proxy 的作用主要体现在三个方面:

  • 拦截和监视外部对对象的访问
  • 降低函数或类的复杂度
  • 在复杂操作前对操作进行校验或对所需资源进行管理

1.2 Proxy场景

实现私有变量

var target = {
   name: 'poetries',
   _age: 22
}

var logHandler = {
  get: function(target,key){
    if(key.startsWith('_')){
      console.log('私有变量age不能被访问')
      return false
    }
    return target[key];
  },
  set: function(target, key, value) {
     if(key.startsWith('_')){
      console.log('私有变量age不能被修改')
      return false
    }
     target[key] = value;
   }
} 
var targetWithLog = new Proxy(target, logHandler);
 
// 私有变量age不能被访问
targetWithLog.name; 
 
// 私有变量age不能被修改
targetWithLog.name = 'others'; 

1.3 proxy VS difineProporty

参考:https://blog.youkuaiyun.com/sinat_17775997/article/details/83989098

var value = 1;

Object.defineProperty({}, "num", {
	get : function(){
		return value;
    },
	set : function(newValue){
     	 value = newValue;
    },
	enumerable : true,
	configurable : true
});

使用 defineProperty 只能重定义属性的读取(get)和设置(set)行为,到了 ES6,提供了 Proxy,可以重定义更多的行为,比如 in、delete、函数调用等更多行为。
除了 get 和 set 之外,proxy 可以拦截多达 13 种操作,比如 has(target, propKey),可以拦截 propKey in proxy 的操作,返回一个布尔值。

又比如说 apply 方法拦截函数的调用、call 和 apply 操作。

apply 方法可以接受三个参数,分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组,不过这里我们简单演示一下:

var target = function () { return 'I am the target'; };
var handler = {
  apply: function () {
    return 'I am the proxy';
  }
};
 
var p = new Proxy(target, handler);
 
p();
// "I am the proxy"

### ES6Proxy 对象的核心特性与使用方法 #### 1. **Proxy 的基本概念** `Proxy` 是 ECMAScript 6ES6)引入的一种新功能,用于拦截并重新定义对象的基本操作行为。它允许开发者在访问或修改目标对象时插入自定义逻辑[^1]。 --- #### 2. **核心组成部分** `Proxy` 主要由两部分组成: - **目标对象 (`target`):** 被代理的对象。 - **处理器 (`handler`):** 定义了一系列陷阱函数(trap functions),用来捕获对目标对象的操作。 以下是 `Proxy` 构造器的标准语法: ```javascript const proxy = new Proxy(target, handler); ``` 其中,`target` 可以是一个普通的对象、数组甚至函数;而 `handler` 则包含了各种可选的方法来拦截不同的操作。 --- #### 3. **常见的陷阱函数及其用途** ##### (1)数据验证——`set` 方法 当尝试设置某个属性的值时,可以通过 `set` 来执行额外的数据校验逻辑。例如: ```javascript let validator = { set: function (obj, prop, value) { if (prop === 'age') { if (!Number.isInteger(value)) { throw new Error('The age must be an integer'); } if (value > 200 || value < 0) { throw new Error('The age seems invalid'); } } obj[prop] = value; return true; } }; let person = new Proxy({}, validator); person.age = 18; // 正常赋值 console.log(person.age); // 输出 18 try { person.age = 'young'; // 抛出错误 } catch (e) { console.error(e.message); // The age must be an integer } ``` 上述代码展示了如何通过 `set` 实现简单的年龄字段校验。 --- ##### (2)读取控制——`get` 方法 可以利用 `get` 拦截对属性的读取请求,并返回经过加工后的结果。比如隐藏敏感信息或者提供默认值: ```javascript let user = { firstName: 'John', lastName: 'Doe' }; let handlerGet = { get: function (target, key) { if (!(key in target)) { return `${key} is not defined`; } return target[key]; } }; let proxiedUser = new Proxy(user, handlerGet); console.log(proxiedUser.firstName); // John console.log(proxiedUser.email); // email is not defined ``` 此示例说明了如何优雅地处理未定义键的情况[^4]。 --- ##### (3)实例化支持——`construct` 和 `apply` 如果目标本身是个构造函数,则可通过 `construct` 或者对于普通函数调用则借助于 `apply` 进行扩展管理[^3]。下面展示了一个例子,演示如何记录每次类实例化的次数: ```javascript function MyClass() {} MyClass.prototype.incrementCount = function () {}; let countHandler = { construct: function (target, args, newTarget) { const instance = Reflect.construct(...arguments); Object.defineProperty(instance, '_count', { writable: true }); instance._count++; return instance; }, }; let CountableClass = new Proxy(MyClass, countHandler); let a = new CountableClass(); a._count++; // 修改计数器变量 console.log(a._count); // 结果为 1 ``` 这里我们看到即使是在复杂场景下也能灵活运用 Proxies 提供的功能。 --- #### 4. **实际应用案例分析** 为了更直观理解其强大之处,在日常开发过程中经常遇到的需求之一就是实时监控某些特定状态的变化情况。这正是前面提到过的关于工程师信息更新的通知机制: ```javascript var engineer = { name: 'Alice', skills: ['JavaScript'] }; var interceptor = { set: function (receiver, property, value) { console.log(`${property} was updated from ${receiver[property]} to ${value}`); receiver[property] = value; } }; new Proxy(engineer, interceptor).skills.push('Python'); // Output: // skills was updated from ["JavaScript"] to ["JavaScript", "Python"] ``` 这段脚本清楚表明每当技能列表发生变化都会打印相应的日志消息出来。 --- ### 总结 综上所述,`Proxy` 不仅赋予了 JavaScript 更加丰富的元编程能力,还极大地增强了应用程序灵活性和可控度。无论是基础的数据验证还是高级别的框架设计都可以找到它的身影[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值