ES6 Proxy 用法总结以及 Object.defineProperty用法区别

Proxy 是 ES6 引入的一种强大的拦截机制,用于定义对象的基本操作(如读取、赋值、删除等)的自定义行为。相较于 Object.definePropertyProxy 提供了更灵活、全面的拦截能力。


1. Proxy 语法

const proxy = new Proxy(target, handler);
  • target:被代理的对象
  • handler:定义拦截行为的对象

2. Proxy 基本用法

(1) 拦截对象的属性访问

const person = {
  name: "Alice",
  age: 25,
};

const proxyPerson = new Proxy(person, {
  get(target, prop) {
    console.log(`访问属性: ${prop}`);
    return prop in target ? target[prop] : "属性不存在";
  },
});

console.log(proxyPerson.name); // 访问属性: name  -> "Alice"
console.log(proxyPerson.gender); // 访问属性: gender  -> "属性不存在"

(2) 拦截对象的属性修改

const proxyPerson = new Proxy(person, {
  set(target, prop, value) {
    if (prop === "age" && typeof value !== "number") {
      throw new Error("年龄必须是数字");
    }
    target[prop] = value;
    console.log(`设置 ${prop}${value}`);
    return true;
  },
});

proxyPerson.age = 30; // 设置 age 为 30
proxyPerson.age = "abc"; // 抛出错误: 年龄必须是数字

(3) 拦截对象的属性删除

const proxyPerson = new Proxy(person, {
  deleteProperty(target, prop) {
    console.log(`删除属性: ${prop}`);
    return delete target[prop];
  },
});

delete proxyPerson.age; // 删除属性: age

(4) 拦截 in 操作符 (has 方法)

const proxyPerson = new Proxy(person, {
  has(target, prop) {
    console.log(`检查属性是否存在: ${prop}`);
    return prop in target;
  },
});

console.log("name" in proxyPerson); // 检查属性是否存在: name -> true
console.log("gender" in proxyPerson); // 检查属性是否存在: gender -> false
const range = { start: 10, end: 50 };

const proxy = new Proxy(range, {
  has(target, prop) {
    return prop >= target.start && prop <= target.end;
  }
});

console.log(15 in proxy); // true
console.log(60 in proxy); // false

(5) 拦截函数调用 (apply 方法)

const multiply = new Proxy((a, b) => a * b, {
  apply(target, thisArg, args) {
    console.log(`调用函数 multiply,参数: ${args}`);
    return target(...args);
  }
});

console.log(multiply(3, 4)); // 调用函数 multiply,参数: 3,4 -> 12

(6) 拦截构造函数 (construct 方法)

const Person = new Proxy(class {
  constructor(name) {
    this.name = name;
  }
}, {
  construct(target, args) {
    console.log(`创建实例,参数: ${args}`);
    return new target(...args);
  }
});

const user = new Person("Alice"); // 创建实例,参数: Alice

特点:

  • 可以 监听整个对象,而不是单个属性。
  • 能拦截 所有操作(如 getsethasdeletePropertyapply 等)。
  • 可以用于 动态代理,使得代码更具扩展性。

3. Proxy 实际使用场景

(1) 数据验证和格式化

const user = new Proxy({}, {
  set(target, prop, value) {
    if (prop === "age" && typeof value !== "number") {
      throw new Error("年龄必须是数字");
    }
    target[prop] = value;
    return true;
  }
});

(2) 实现私有属性和方法

const createUser = () => {
  const privateData = new WeakMap();

  return new Proxy({}, {
    get(target, prop) {
      if (prop.startsWith("_")) {
        throw new Error("无法访问私有属性");
      }
      return target[prop];
    }
  });
};

(3) 添加日志记录和调试功能

const logger = new Proxy({}, {
  get(target, prop) {
    console.log(`访问属性: ${prop}`);
    return target[prop];
  }
});

(4) 提供默认值和只读访问

const defaultSettings = new Proxy({}, {
  get(target, prop) {
    return prop in target ? target[prop] : "默认值";
  },
  set() {
    throw new Error("设置操作被禁止");
  }
});

(5) 实现惰性加载和缓存

const lazyObject = new Proxy({}, {
  get(target, prop) {
    if (!(prop in target)) {
      console.log(`初始化 ${prop}`);
      target[prop] = prop.toUpperCase();
    }
    return target[prop];
  }
});

(6) 解决 this 指向问题

const obj = {
  name: "Alice",
  greet() {
    return `Hello, ${this.name}`;
  }
};

const proxyObj = new Proxy(obj, {
  get(target, prop, receiver) {
    return typeof target[prop] === "function" ? target[prop].bind(target) : target[prop];
  }
});

const greet = proxyObj.greet;
console.log(greet()); // Hello, Alice

4.Object.defineProperty

Object.defineProperty() 允许直接在对象上定义新的属性,或者修改已有属性的特性(如可读写性、是否可枚举等)。

示例:

const person = {};

Object.defineProperty(person, "name", {
  value: "Alice",
  writable: false, // 不能修改
  enumerable: true,
  configurable: false
});

console.log(person.name); // Alice
person.name = "Bob"; // 失败,严格模式下会报错
console.log(person.name); // Alice

特点:

  • 只能加工 单个属性,不能监听整个对象。
  • 只能 定义静态的行为,不能动态处理对象属性的操作。
  • 不能拦截 删除新增属性函数调用

5. ProxyObject.defineProperty 详细对比

特性Object.definePropertyProxy
监听属性读取❌ 不支持✅ 支持 (get)
监听属性赋值✅ 支持 (set)✅ 支持 (set)
监听属性删除❌ 不支持✅ 支持 (deleteProperty)
监听属性存在性❌ 不支持✅ 支持 (has) (in 关键字)
监听对象新增属性❌ 不支持✅ 支持 (set)
监听函数调用❌ 不支持✅ 支持 (apply)
监听构造函数❌ 不支持✅ 支持 (construct)
监听整个对象❌ 需要对每个属性定义✅ 一次性监听整个对象
适用于数组或集合❌ 不适合✅ 适合
可扩展性❌ 需手动定义✅ 更强大,支持代理嵌套

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/967495.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

物联网软件开发与应用方向应该怎样学习,学习哪些内容,就业方向是怎样?(文末领取整套学习视频,课件)物联网硬件开发与嵌入式系统

随着物联网技术的飞速发展&#xff0c;物联网软件开发与应用方向成为了众多开发者关注的焦点。那么&#xff0c;如何在这个领域中脱颖而出呢&#xff1f;本文将为你提供一份详细的学习指南&#xff0c;帮助你从零开始&#xff0c;逐步掌握物联网软件开发与应用的核心技能。 一…

Linux——基础命令1

$&#xff1a;普通用户 #&#xff1a;超级用户 cd 切换目录 cd 目录 &#xff08;进入目录&#xff09; cd ../ &#xff08;返回上一级目录&#xff09; cd ~ &#xff08;切换到当前用户的家目录&#xff09; cd - &#xff08;返回上次目录&#xff09; pwd 输出当前目录…

OpenFeign远程调用返回的是List<T>类型的数据

在使用 OpenFeign 进行远程调用时&#xff0c;如果接口返回的是 List 类型的数据&#xff0c;可以通过以下方式处理&#xff1a; 直接定义返回类型为List Feign 默认支持 JSON 序列化/反序列化&#xff0c;如果服务端返回的是 List的JSON格式数据&#xff0c;可以直接在 Feig…

向量数据库简单对比

文章目录 一、Chroma二、Pinecone/腾讯云VectorDB/VikingDB三、redis四、Elasticsearch五、Milvus六、Qdrant七、Weaviate八、Faiss 一、Chroma 官方地址&#xff1a; https://www.trychroma.com/优点 ①简单&#xff0c;非常简单构建服务。 ②此外&#xff0c;Chroma还具有自…

字符指针、数组指针和函数指针

1. 字符指针变量 1.1 简单例子 字符指针 char* 在C语言中主要由两种用法&#xff1a; 1.用于存放一个字符变量的地址。 2.用字符指针接收一个字符串。 这里并不是将整个字符串的地址存入 pstr 指针&#xff0c;指针变量 pstr 中存放的是常量字符串的首字符 h 的地址。 以一个…

【Linux网络编程】之守护进程

【Linux网络编程】之守护进程 进程组进程组的概念组长进程 会话会话的概念会话ID 控制终端控制终端的概念控制终端的作用会话、终端、bash三者的关系 前台进程与后台进程概念特点查看当前终端的后台进程前台进程与后台进程的切换 作业控制相关概念作业状态&#xff08;一般指后…

JS宏进阶:XMLHttpRequest对象

一、概述 XMLHttpRequest简称XHR&#xff0c;它是一个可以在JavaScript中使用的对象&#xff0c;用于在后台与服务器交换数据&#xff0c;实现页面的局部更新&#xff0c;而无需重新加载整个页面&#xff0c;也是Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;…

怎么查看电脑显存大小(查看电脑配置)

这里提供一个简单的方法查看 winr打开cmd 终端输入dxdiag进入DirectX 点击显示查看设备的显示内存&#xff08;VRAM&#xff09; 用这个方法查看电脑配置和显存是比较方便的 dxdiag功能 Dxdiag是Windows的DirectX诊断工具&#xff0c;其主要作用包括但不限于以下几点&#…

优惠券平台(一):基于责任链模式创建优惠券模板

前景概要 系统的主要实现是优惠券的相关业务&#xff0c;所以对于用户管理的实现我们简单用拦截器在触发接口前创建一个单一用户。 // 用户属于非核心功能&#xff0c;这里先通过模拟的形式代替。后续如果需要后管展示&#xff0c;会重构该代码 UserInfoDTO userInfoDTO new…

【机器学习】数据预处理之scikit-learn的Scaler与自定义Scaler类进行数据归一化

scikit-learn的Scaler数据归一化 一、摘要二、训练数据集和测试数据集的归一化处理原则三、scikit-learn中的Scalar类及示例四、自定义StandardScaler类进行数据归一化处理五、小结 一、摘要 本文主要介绍了scikit-learn中Scaler的使用方法&#xff0c;特别强调了数据归一化在…

机器学习中过拟合和欠拟合问题处理方法总结

目录 一、背景二、过拟合(Overfitting)2.1 基本概念2.2 过拟合4个最主要的特征2.3 防止过拟合的11个有效方法 三、欠拟合&#xff08;Underfitting&#xff09;3.1 基本概念3.2 欠拟合的4个特征3.3 防止欠拟合的11个有效方法 四、总结五、参考资料 一、背景 在机器学习模型训练…

ABP框架9——自定义拦截器的实现与使用

一、AOP编程 AOP定义:面向切片编程&#xff0c;着重强调功能&#xff0c;将功能从业务逻辑分离出来。AOP使用场景&#xff1a;处理通用的、与业务逻辑无关的功能&#xff08;如日志记录、性能监控、事务管理等&#xff09;拦截器:拦截方法调用并添加额外的行为&#xff0c;比如…

基于YoloV11和驱动级鼠标模拟实现Ai自瞄

本文将围绕基于 YoloV11 和驱动级鼠标实现 FPS 游戏 AI 自瞄展开阐述。 需要着重强调的是&#xff0c;本文内容仅用于学术研究和技术学习目的。严禁任何个人或组织将文中所提及的技术、方法及思路应用于违法行为&#xff0c;包括但不限于在各类游戏中实施作弊等违规操作。若因违…

示例代码:C# MQTTS双向认证(客户端)(服务器EMQX)

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

记录IMX6ULL开发板上移植SQLite3并运行Qt程序

文章目录 概要移植SQLite3Qt程序部署实验现象 概要 基于上一章对使用Qt运行对应的实验实例来完成对用户使用ui界面完成对SQLite数据库的增删改查等操作。本文旨在对上一句节的Qt程序部署到IMX6ULL开发板&#xff0c;并且完成对SQLite数据库在IMX6ULL开发板上的移植。 移植SQ…

达梦数据库(DM)线程管理

目录标题 达梦数据库&#xff08;DM&#xff09;线程管理笔记一、DM 线程架构概述二、DM 主要线程类型及功能&#xff08;一&#xff09;监听线程&#xff08;二&#xff09;工作线程&#xff08;三&#xff09;IO 线程&#xff08;四&#xff09;调度线程&#xff08;五&#…

02.10 TCP之文件传输

1.思维导图 2.作业 服务器代码&#xff1a; #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> …

Node.js 环境配置

什么是 Node.js Node.js 是一个基于 Chrome V8 JavaScript 引擎的 JavaScript 运行时环境&#xff0c;它允许你在服务器端运行 JavaScript。传统上&#xff0c;JavaScript 主要用于浏览器中的前端开发&#xff0c;而 Node.js 使得 JavaScript 也能够在服务器上执行&#xff0c;…

【办公类-53-04】20250209Python模仿制作2024学年第二学期校历

背景需求&#xff1a; 马上开学了&#xff0c;又要制作校历&#xff08;删划节假日&#xff09;。之前我都是用网络的图片&#xff0c;然后在PPT里修改。 存在问题&#xff1a; 网络校历是从周日开始的&#xff0c;但日常我们老师做教案&#xff0c;都是默认从周一到周五&…

KERL文献阅读分享:知识图谱与预训练语言模型赋能会话推荐系统

标题期刊年份Knowledge Graphs and Pre-trained Language Models enhanced Representation Learning for Conversational Recommender SystemsJournal of LaTeX Class Files2021 &#x1f4c8;研究背景 在数字时代&#xff0c;个性化推荐系统已经成为了我们生活的一部分。从电…