一文大白话讲清楚ES6代理Proxy和反射Reflect

文章目录

  • 一文大白话讲清楚ES6代理Proxy和反射Reflect
  • 1. 你当过老板么
  • 2.代理Proxy
    • 2.1 get(target,propKey,receiver)//获取对象的属性
    • 2.2 set(target,propKey,newValue,receiver)//设置属性的值
    • 2.3 has(target,propKey)//代理查询属性操作,propKey in obj的操作
    • 2.4 deleteProperty(target,propKey),代理属性删除操作,delete obj.属性
    • 2.5 ownKeys(target)拦截属性查询操作,Object.keys(),Object.getOwnPropertyNames(),Object.getOwnPropertySymbols()等
    • 2.6 getOwnPropertyDescriptor 代理Object。getOwnPropertyDescriptor(obj,propKey)
    • 2.7 defineProperty(target,propKey,PropDesc),代理Object.defineProperty
    • 2.8 preventExtensions(target),代理:拦截 Object.preventExtensions(proxy),禁止对象可扩展
    • 2.9 isExtensible(target),代理Object.isExtensible
    • 2.10 getPrototypeOf(target),代理Object.getPrototypeOf(target)
    • 2.11 apply(target,object,args),代理Proxy作为函数调用的操作
    • 2.11 construct(target,args),代理new 操作
  • 3. 反射Reflect

一文大白话讲清楚ES6代理Proxy和反射Reflect

1. 你当过老板么

  • 老板很忙,很多事自己忙不过来,怎么办,找一个秘书,给秘书授权,以他的名义去做事。
  • 那简单了,老板能做的我都能做,这就是代理
  • 我做完了,总得汇报给老板,让老板信息同步吧,好嘛,这就是反射
  • 回到js,我们有一个对象A,不直接操作对象A,而是找来B,让B成为A的代理,然后去操作B。B操作完了再去同步到A。这就是代理和反射

2.代理Proxy

  • 用于定于对象基本操作的自定义行为
  • 说白了,就是修改程序的默认行为,想好比在编程语言层面上做修改,属于元编程
  • 再简单点理解,就是把操作对象的底层方法进行覆写
  • 啥意思,就是假设有一个对象,obj={name:‘tom’},正常情况下我们obj.name就能获取到tom。但是我现在不想获取到tom,我让obj.name干点别的,行不行,行,比如让obj.name返回shift
  • 上代码
let obj={name:'tom'
}
// 用proxy代理obj
let proxy=new Proxy(obj,{//proxy.name的返回值get(target,name,reciever){return 'shift'}
})
console.log(obj.name)//tom
console.log(proxy.name)//shift
  • 明白了吧,proxy的任务就是代理obj,
  • 那都能代理obj的哪些方法呢

2.1 get(target,propKey,receiver)//获取对象的属性

  • 上面举了例子了

2.2 set(target,propKey,newValue,receiver)//设置属性的值

let obj={name:'tom'
}
let proxy=new Proxy(obj,{set(target,propKey,newValue,reciever){//如果设置proxy.name,就执行下边这句话,把obj.name改为'hahaha'target[propKey]='hahaha'}
})
proxy.name='new Tom'//这里设置name的新值为newTOm
console.log(proxy.name)//hahaha,但最终打印出来的是hahaha

2.3 has(target,propKey)//代理查询属性操作,propKey in obj的操作

let obj={name:'name'
}
let proxy=new Proxy(obj,{has(target,propKey){if(propKey==='age'){return true}}
})
console.log(age in obj)//false,obj里面没有age属性,所以返回false
console.log(age in proxy)//true,proxy里面也灭有age,但是我们拦截覆写了has方法,让他返回rue

2.4 deleteProperty(target,propKey),代理属性删除操作,delete obj.属性

let obj={name:'name',age:'age',
}
let proxy=new Proxy(obj,{deleteProperty(target,propKey){if(propKey==='name'){Reflect.deleteProperty(target,propKey)//如果删除name属性,就正常删除}else if(propKey==='age'){return false//如果删除age属性,则直接返回false,表示删除失败}}
})
console.log(proxy)//{ name: 'name', age: 'age' }
delete proxy.name
delete proxy.age
console.log(proxy)//{ age: 'age' },age属性并没有删除掉

2.5 ownKeys(target)拦截属性查询操作,Object.keys(),Object.getOwnPropertyNames(),Object.getOwnPropertySymbols()等

let obj={name:'tom',age:12
}
let proxy=new Proxy(obj,{ownKeys(target){return ['d','f','g']}
})
console.log(Object.getOwnPropertyNames(proxy))//[ 'd', 'f', 'g' ],正常应该打印['name','age']

2.6 getOwnPropertyDescriptor 代理Object。getOwnPropertyDescriptor(obj,propKey)

let obj={name:'tom',age:12
}
let proxy=new Proxy(obj,{getOwnPropertyDescriptor(target,propKey){return{ value: 'ProxyTom', writable: true, enumerable: true, configurable: true }}
})
console.log(Object.getOwnPropertyDescriptor(proxy,'name'))//正常应该返回{ value: 'tom', writable: true, enumerable: true, configurable: true }
//实际返回
// {
//     value: 'ProxyTom',
//         writable: true,
//     enumerable: true,
//     configurable: true
// }

2.7 defineProperty(target,propKey,PropDesc),代理Object.defineProperty

let obj={name:'tom',age:12
}
let proxy=new Proxy(obj,{defineProperty(target,propKey,propDesc){return Object.defineProperty(target,propKey,{value:'166cm',writable:true,configurable:true,enumerable:true,})}
})
Object.defineProperty(proxy,'height',{value:'163cm',writable:true,configurable:true,enumerable:true,
})
console.log(proxy)//{ name: 'tom', age: 12, height: '166cm' },正常情况下应该打印163cm,是因为对defineProperty进行了覆写

2.8 preventExtensions(target),代理:拦截 Object.preventExtensions(proxy),禁止对象可扩展

let obj={name:'tom'
}
let proxy=new Proxy(obj,{preventExtesions(target){return false}
})
Object.preventExtensions(proxy)//设置对象不可扩展,这里会报错,阻止禁止扩展的行为

2.9 isExtensible(target),代理Object.isExtensible

let obj={name:'tom'
}
let proxy=new Proxy(obj,{isExtensible(target){return Reflect.isExtensible(target)},})
Object.preventExtensions(proxy)//设置对象不可扩展,这里会报错,阻止禁止扩展的行为
console.log(Object.isExtensible(proxy))//false

2.10 getPrototypeOf(target),代理Object.getPrototypeOf(target)

let obj={name:'tom'
}
let proxy=new Proxy(obj,{getPrototypeOf(target){return {age:12}},})console.log(Object.getPrototypeOf(proxy))//{ age: 12 },正常情况下应该打印{}

2.11 apply(target,object,args),代理Proxy作为函数调用的操作

let fn=function (){return 1
}
console.log(fn())//1
let proxy=new Proxy(fn,{apply(target,object,args){return 4}
})
let g=function (){}
console.log(proxy.call(g))//4

2.11 construct(target,args),代理new 操作

let fn=function (){this.name='tom'
}
let proxy=new Proxy(fn,{construct(target,args){return {name:'new-tom'}}
})
let p=new proxy()
console.log(p)//{ name: 'new-tom' }//正常打印{ name: 'tom' }

3. 反射Reflect

  • 上面我们都是在代理对象proxy上操作,源对象obj并没有得到同步
  • Reflect的作用就是把对proxy的操作同步到obj上
  • 每个Proxy代理的方法,Reflect都有同名对应的方法取反射
  • 上代码
let obj={name:'tom'
}
let proxy=new Proxy(obj,{set(target,propKey,newVale,receiver){Reflect.set(target,propKey,newVale,receiver)//同步映射到obj}
})
proxy.age=12;
console.log(proxy)
console.log(obj)
// { name: 'tom', age: 12 }
// { name: 'tom', age: 12 }
  • 其他2.1——2.11原理都是一样的,不做一一演示,大家自行写一下

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VS2022引入sqlite数据库交互

法一:用官网编译好的动态库(推荐) 下载所需文件 sqlite官网地址:https://www.sqlite.org/howtocompile.html 下载以下的2个压缩包 第一个压缩包 sqlite-amalgamation-xxxx.zip,xxxx是版本号,保持一致即可,这里面有sqite3.h 第…

Java后端常用的4种请求方式(通俗易懂)

文章目录 前言通用接口类(ControllerDemo)通用实体类(UserEntity)通用响应类(HttpClientResult)成功截图(先启动项目,然后右键执行main方法) HttpClientHttpClient 的主要类代码案例导入依赖工具类(HttpClientUtil)测试类 HttpURLConnection简介调用步骤代码案例导入依赖工具类…

STM32烧写失败之Contents mismatch at: 0800005CH (Flash=FFH Required=29H) !

一)问题:用ULINK2给STM32F103C8T6下载程序,下载方式设置如下: 出现下面两个问题: 1)下载问题界面如下: 这个错误的信息大概可以理解为,在0x08000063地址上读取到flash存储为FF&am…

Dynamic-Datasource 文档

dynamic-datasource-spring-boot-starter是一个基于springboot的快速集成多数据源的启动器。 特性 支持数据源分组,适用于多种场景,纯粹多库、读写分离、一主多从、混合模式。支持数据库敏感配置信息加密(可自定义)ENC()。支持每个数据库独立初始化表结…

P10424 [蓝桥杯 2024 省 B] 好数

题目描述 一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位……)上的数字是奇数,偶数位(十位、千位、十万位……)上的数字是偶数,我们就称之为“好数”。 给定一个正整数 N&#xf…

Spring Boot教程之五十二:CrudRepository 和 JpaRepository 之间的区别

Spring Boot – CrudRepository 和 JpaRepository 之间的区别 Spring Boot建立在 Spring 之上,包含 Spring 的所有功能。由于其快速的生产就绪环境,使开发人员能够直接专注于逻辑,而不必费力配置和设置,因此如今它正成为开发人员…

LLM的MoE由什么构成:门控网络,专家网络

LLM的MoE由什么构成:门控网络,专家网络 目录 LLM的MoE由什么构成:门控网络,专家网络专家网络门控网络MoE在联邦学习中的使用及原理专家网络 定义与特点:是一组独立的模型,每个模型都负责处理某个特定的子任务或学习输入空间的特定部分。这些专家可以是简单的线性回归模型…

DeepSeek-V3与GPT-4o的对比详解

DeepSeek-V3,作为一款引人注目的开源大型语言模型,自其诞生以来,便以卓越的性能和高效的性价比,在AI界掀起了一股新的浪潮。本文将详细介绍DeepSeek-V3的诞生背景、技术优势,以及与顶尖闭源模型GPT-4o的对比&#xff0…

Mysql 性能优化:覆盖索引

概述 覆盖索引(Covering Index)是一个 MySQL 查询优化技术,它指的是一个索引包含了查询所需的所有字段的数据,因此不需要回表(访问数据表的行)就可以完成查询。使用覆盖索引可以显著提高查询性能&#xff…

python注意事项:range遍历越索引现象、列表边遍历边修改出现的问题

文章目录 前言一、range遍历越索引现象QS1:遍历range(2,2)会发生什么?不会报错,但是也不会遍历到任何内容QS1:遍历range(3,2)会发生什么?不会报错,但是也不会遍历到任何内容 二、列表边遍历边修改注意事项(Java的List系…

【SQL】Delete使用

目录 语法 需求 示例 分析 代码 语法 DELETE删除表中所需内容 删除表中满足特点条件的行:DELETE FROM 表名 WHERE 条件; 删除表中所有行:DELETE FROM 表名; WHERE子句 WHERE子句用于指定从表中选取记录的条件。允许筛选数据,只返回满足…

【express-generator】05-路由中间件和错误处理(第一阶段收尾)

一、前言 上篇文章我们介绍了express-generator的请求体解析,重点讲了常用的请求体数据格式(JSON/URL 编码的表单数据)以及一个FILE文件上传,同时搭配代码示范进行辅助理解。 二、本篇重点 我们继续第一阶段的知识,…

Vue3(elementPlus) el-table替换/隐藏行箭头,点击整行展开

element文档链接: https://element-plus.org/zh-CN/component/form.html 一、el-table表格行展开关闭箭头替换成加减号 注:Vue3在样式中修改箭头图标无效,可能我设置不对,欢迎各位来交流指导 转变思路:隐藏箭头&…

【Javascript Day1】javascript基础

javascript编程规则 弹窗&#xff08;举例&#xff09; alert("内容")&#xff0c;直接写在控制区生效 三种写法 1、行内js语法 &#xff1a;需要注意引号的问题 <input type"button" value"提示窗" οnclick alert("消息") &…

GitLab创建用户,设置访问SSH Key

继上一篇 Linux Red Hat 7.9 Server安装GitLab-CSDN博客 安装好gitlab&#xff0c;启用管理员root账号后&#xff0c;开始创建用户账户 1、创建用户账户 进入管理后台页面 点击 New User 输入用户名、邮箱等必填信息和登录密码 密码最小的8位&#xff0c;不然会不通过 拉到…

QT鼠标、键盘事件

一、鼠标 鼠标点击 mousePressEvent 鼠标释放 mouseReleaseEvent 鼠标移动 mouseMoveEvent 鼠标双击 mouseDoubleClickEvent 鼠标滚轮 QWheelEvent 二、键盘 键盘按下 keyPressEvent 键盘松开keyReleaseEvent 一、鼠标 #include <QMouseEvent> 鼠标点击 mouse…

数据库环境安装(day1)

网址&#xff1a;MySQL 下载&#xff08;环境准备&#xff09;&#xff1a; &#xff08;2-5点击此处&#xff0c;然后选择合适的版本&#xff09; 1.linux在线YUM仓库 下载/安装: wget https://repo.mysql.com//mysql84-community-release-el9-1.noarch.rpm rpm -i https://r…

Qt 5.14.2 学习记录 —— 칠 QWidget 常用控件(2)

文章目录 1、Window Frame2、windowTitle3、windowIcon4、qrc机制5、windowOpacity 1、Window Frame 在运行Qt程序后&#xff0c;除了用户做的界面&#xff0c;最上面还有一个框&#xff0c;这就是window frame框。对于界面的元素&#xff0c;它们的原点是Qt界面的左上角或win…

以太网协议在汽车应用中的动与静

为了让网络中的设备能够随时或随地接入网络或离开网络&#xff0c;做到&#xff1a;接入时无需多余的配置就能和其他设备互相通信&#xff1b;离开时又不会导致设备或网络崩溃。以太网从物理层到协议层展现出多方面的灵活性&#xff0c;&#xff0c;使其成为连接各种设备和系统…

牛客网刷题 ——C语言初阶(6指针)——BC105 矩阵相等判定

1. 题目描述&#xff1a;BC105 矩阵相等判定 牛客网OJ题链接 描述&#xff1a; KiKi得到了两个n行m列的矩阵&#xff0c;他想知道两个矩阵是否相等&#xff0c;请你回答他。(当两个矩阵对应数组元素都相等时两个矩阵相等)。 示例1 输入&#xff1a; 2 2 1 2 3 4 1 2 3 4 输出…