[{"data":1,"prerenderedAt":790},["ShallowReactive",2],{"doc-\u002Fdocs\u002Fjs-proxy-reflect":3,"docs-all":608},{"id":4,"title":5,"body":6,"category":592,"date":593,"description":594,"draft":595,"extension":596,"meta":597,"navigation":598,"path":599,"seo":600,"source":601,"stem":602,"tags":603,"__hash__":607},"docs\u002Fdocs\u002Fjs-proxy-reflect.md","Proxy 与 Reflect 入门",{"type":7,"value":8,"toc":586},"minimark",[9,14,22,26,29,252,262,266,280,438,441,538,541,560,563,582],[10,11,13],"h1",{"id":12},"proxy-与-reflect","Proxy 与 Reflect",[15,16,17,21],"p",{},[18,19,20],"code",{},"new Proxy(target, handler)"," 为目标建立代理，通过 handler 中的 trap 拦截操作。目标对象本身仍可被直接访问，只有经由代理发生的操作才经过相应拦截。",[23,24,25],"h2",{"id":25},"读取与赋值",[15,27,28],{},"课程给读取结果加上前缀，并通过 Reflect 完成实际读写。下面保留这个例子：",[30,31,36],"pre",{"className":32,"code":33,"language":34,"meta":35,"style":35},"language-js shiki shiki-themes github-light github-dark","const target = { uname: 'kevin', age: 12 };\nconst proxy = new Proxy(target, {\n  get(target, key, receiver) {\n    return '哈哈哈' + Reflect.get(target, key, receiver);\n  },\n  set(target, key, value, receiver) {\n    return Reflect.set(target, key, value, receiver);\n  }\n});\nconsole.log(proxy.uname); \u002F\u002F 哈哈哈kevin\nconsole.log(proxy.age); \u002F\u002F 哈哈哈12\nproxy.uname = 'lily';\nconsole.log(proxy.uname, target.uname); \u002F\u002F 哈哈哈lily lily\n","js","",[18,37,38,71,91,118,139,145,170,183,189,195,211,224,239],{"__ignoreMap":35},[39,40,43,47,51,54,58,62,65,68],"span",{"class":41,"line":42},"line",1,[39,44,46],{"class":45},"szBVR","const",[39,48,50],{"class":49},"sj4cs"," target",[39,52,53],{"class":45}," =",[39,55,57],{"class":56},"sVt8B"," { uname: ",[39,59,61],{"class":60},"sZZnC","'kevin'",[39,63,64],{"class":56},", age: ",[39,66,67],{"class":49},"12",[39,69,70],{"class":56}," };\n",[39,72,74,76,79,81,84,88],{"class":41,"line":73},2,[39,75,46],{"class":45},[39,77,78],{"class":49}," proxy",[39,80,53],{"class":45},[39,82,83],{"class":45}," new",[39,85,87],{"class":86},"sScJk"," Proxy",[39,89,90],{"class":56},"(target, {\n",[39,92,94,97,100,104,107,110,112,115],{"class":41,"line":93},3,[39,95,96],{"class":86},"  get",[39,98,99],{"class":56},"(",[39,101,103],{"class":102},"s4XuR","target",[39,105,106],{"class":56},", ",[39,108,109],{"class":102},"key",[39,111,106],{"class":56},[39,113,114],{"class":102},"receiver",[39,116,117],{"class":56},") {\n",[39,119,121,124,127,130,133,136],{"class":41,"line":120},4,[39,122,123],{"class":45},"    return",[39,125,126],{"class":60}," '哈哈哈'",[39,128,129],{"class":45}," +",[39,131,132],{"class":56}," Reflect.",[39,134,135],{"class":86},"get",[39,137,138],{"class":56},"(target, key, receiver);\n",[39,140,142],{"class":41,"line":141},5,[39,143,144],{"class":56},"  },\n",[39,146,148,151,153,155,157,159,161,164,166,168],{"class":41,"line":147},6,[39,149,150],{"class":86},"  set",[39,152,99],{"class":56},[39,154,103],{"class":102},[39,156,106],{"class":56},[39,158,109],{"class":102},[39,160,106],{"class":56},[39,162,163],{"class":102},"value",[39,165,106],{"class":56},[39,167,114],{"class":102},[39,169,117],{"class":56},[39,171,173,175,177,180],{"class":41,"line":172},7,[39,174,123],{"class":45},[39,176,132],{"class":56},[39,178,179],{"class":86},"set",[39,181,182],{"class":56},"(target, key, value, receiver);\n",[39,184,186],{"class":41,"line":185},8,[39,187,188],{"class":56},"  }\n",[39,190,192],{"class":41,"line":191},9,[39,193,194],{"class":56},"});\n",[39,196,198,201,204,207],{"class":41,"line":197},10,[39,199,200],{"class":56},"console.",[39,202,203],{"class":86},"log",[39,205,206],{"class":56},"(proxy.uname); ",[39,208,210],{"class":209},"sJ8bj","\u002F\u002F 哈哈哈kevin\n",[39,212,214,216,218,221],{"class":41,"line":213},11,[39,215,200],{"class":56},[39,217,203],{"class":86},[39,219,220],{"class":56},"(proxy.age); ",[39,222,223],{"class":209},"\u002F\u002F 哈哈哈12\n",[39,225,227,230,233,236],{"class":41,"line":226},12,[39,228,229],{"class":56},"proxy.uname ",[39,231,232],{"class":45},"=",[39,234,235],{"class":60}," 'lily'",[39,237,238],{"class":56},";\n",[39,240,242,244,246,249],{"class":41,"line":241},13,[39,243,200],{"class":56},[39,245,203],{"class":86},[39,247,248],{"class":56},"(proxy.uname, target.uname); ",[39,250,251],{"class":209},"\u002F\u002F 哈哈哈lily lily\n",[15,253,254,255,257,258,261],{},"这个前缀用于演示，实际会把数字也变成字符串，不适合透明代理。",[18,256,179],{}," trap 应返回布尔结果；返回假值时严格模式赋值会抛错。使用 ",[18,259,260],{},"Reflect.set()"," 可以把底层操作的成功状态传回去。",[23,263,265],{"id":264},"receiver-的作用","receiver 的作用",[15,267,268,271,272,275,276,279],{},[18,269,270],{},"Reflect.get(target, key, receiver)"," 的第三个参数影响 getter 内的 ",[18,273,274],{},"this","。直接用 ",[18,277,278],{},"target[key]"," 会把 getter 的接收者固定为 target，可能绕开代理上的其他读取。",[30,281,283],{"className":32,"code":282,"language":34,"meta":35,"style":35},"const target = {\n  name: 'kevin',\n  get greeting() { return `hello ${this.name}`; }\n};\nconst proxy = new Proxy(target, {\n  get(target, key, receiver) {\n    if (key === 'name') return 'lily';\n    return Reflect.get(target, key, receiver);\n  }\n});\nconsole.log(proxy.greeting); \u002F\u002F hello lily\nconsole.log(target.greeting); \u002F\u002F hello kevin\n",[18,284,285,296,306,336,341,355,373,396,406,410,414,426],{"__ignoreMap":35},[39,286,287,289,291,293],{"class":41,"line":42},[39,288,46],{"class":45},[39,290,50],{"class":49},[39,292,53],{"class":45},[39,294,295],{"class":56}," {\n",[39,297,298,301,303],{"class":41,"line":73},[39,299,300],{"class":56},"  name: ",[39,302,61],{"class":60},[39,304,305],{"class":56},",\n",[39,307,308,310,313,316,319,322,324,327,330,333],{"class":41,"line":93},[39,309,96],{"class":45},[39,311,312],{"class":86}," greeting",[39,314,315],{"class":56},"() { ",[39,317,318],{"class":45},"return",[39,320,321],{"class":60}," `hello ${",[39,323,274],{"class":49},[39,325,326],{"class":60},".",[39,328,329],{"class":56},"name",[39,331,332],{"class":60},"}`",[39,334,335],{"class":56},"; }\n",[39,337,338],{"class":41,"line":120},[39,339,340],{"class":56},"};\n",[39,342,343,345,347,349,351,353],{"class":41,"line":141},[39,344,46],{"class":45},[39,346,78],{"class":49},[39,348,53],{"class":45},[39,350,83],{"class":45},[39,352,87],{"class":86},[39,354,90],{"class":56},[39,356,357,359,361,363,365,367,369,371],{"class":41,"line":147},[39,358,96],{"class":86},[39,360,99],{"class":56},[39,362,103],{"class":102},[39,364,106],{"class":56},[39,366,109],{"class":102},[39,368,106],{"class":56},[39,370,114],{"class":102},[39,372,117],{"class":56},[39,374,375,378,381,384,387,390,392,394],{"class":41,"line":172},[39,376,377],{"class":45},"    if",[39,379,380],{"class":56}," (key ",[39,382,383],{"class":45},"===",[39,385,386],{"class":60}," 'name'",[39,388,389],{"class":56},") ",[39,391,318],{"class":45},[39,393,235],{"class":60},[39,395,238],{"class":56},[39,397,398,400,402,404],{"class":41,"line":185},[39,399,123],{"class":45},[39,401,132],{"class":56},[39,403,135],{"class":86},[39,405,138],{"class":56},[39,407,408],{"class":41,"line":191},[39,409,188],{"class":56},[39,411,412],{"class":41,"line":197},[39,413,194],{"class":56},[39,415,416,418,420,423],{"class":41,"line":213},[39,417,200],{"class":56},[39,419,203],{"class":86},[39,421,422],{"class":56},"(proxy.greeting); ",[39,424,425],{"class":209},"\u002F\u002F hello lily\n",[39,427,428,430,432,435],{"class":41,"line":226},[39,429,200],{"class":56},[39,431,203],{"class":86},[39,433,434],{"class":56},"(target.greeting); ",[39,436,437],{"class":209},"\u002F\u002F hello kevin\n",[23,439,440],{"id":440},"可拦截的操作",[442,443,444,457],"table",{},[445,446,447],"thead",{},[448,449,450,454],"tr",{},[451,452,453],"th",{},"操作",[451,455,456],{},"trap",[458,459,460,483,499,512,525],"tbody",{},[448,461,462,470],{},[463,464,465,466,469],"td",{},"读取、赋值、",[18,467,468],{},"in","、删除",[463,471,472,474,475,474,477,474,480],{},[18,473,135],{},"、",[18,476,179],{},[18,478,479],{},"has",[18,481,482],{},"deleteProperty",[448,484,485,488],{},[463,486,487],{},"自身属性键、描述符、定义属性",[463,489,490,474,493,474,496],{},[18,491,492],{},"ownKeys",[18,494,495],{},"getOwnPropertyDescriptor",[18,497,498],{},"defineProperty",[448,500,501,504],{},[463,502,503],{},"原型读写",[463,505,506,474,509],{},[18,507,508],{},"getPrototypeOf",[18,510,511],{},"setPrototypeOf",[448,513,514,517],{},[463,515,516],{},"扩展性读写",[463,518,519,474,522],{},[18,520,521],{},"isExtensible",[18,523,524],{},"preventExtensions",[448,526,527,530],{},[463,528,529],{},"函数调用、构造",[463,531,532,474,535],{},[18,533,534],{},"apply",[18,536,537],{},"construct",[15,539,540],{},"共 13 种；函数调用和构造要求目标具备相应能力，普通对象不会因为设置 trap 就变成函数。",[15,542,543,544,546,547,474,554,559],{},"Reflect 提供对应的底层操作方法，便于在拦截中继续执行默认行为。Proxy 仍受对象不变量约束，例如不可配置且不可写的数据属性，",[18,545,135],{}," 不能返回与真实值不同的结果。因此前缀例子也不能无条件套用到冻结对象。",[548,549,553],"a",{"href":550,"rel":551},"https:\u002F\u002Ftc39.es\u002Fecma262\u002Fmultipage\u002Freflection.html",[552],"nofollow","ECMAScript Reflect 规范",[548,555,558],{"href":556,"rel":557},"https:\u002F\u002Ftc39.es\u002Fecma262\u002Fmultipage\u002Fordinary-and-exotic-objects-behaviours.html#sec-proxy-object-internal-methods-and-internal-slots",[552],"Proxy 内部方法约束","。",[23,561,562],{"id":562},"来源记录",[564,565,566,573,579],"ul",{},[567,568,569,572],"li",{},[18,570,571],{},"005_less_gulp\u002Fcode\u002Freadme.md"," 第 1 节：Proxy、Reflect 和 13 种操作。",[567,574,575,578],{},[18,576,577],{},"005_less_gulp\u002Fcode\u002F01_proxy.js","：读取前缀与赋值转发。",[567,580,581],{},"receiver 的 getter 示例与对象不变量说明为整理补充，用于解释原代码为何传递第三个参数。",[583,584,585],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":35,"searchDepth":93,"depth":93,"links":587},[588,589,590,591],{"id":25,"depth":73,"text":25},{"id":264,"depth":73,"text":265},{"id":440,"depth":73,"text":440},{"id":562,"depth":73,"text":562},"fundamentals","2023-04-26","通过属性读取和赋值示例理解 Proxy、Reflect、receiver 与拦截限制。",false,"md",{},true,"\u002Fdocs\u002Fjs-proxy-reflect",{"title":5,"description":594},"尚学堂 ES6 课程 005_less_gulp\u002Fcode\u002F01_proxy.js 与 readme.md","docs\u002Fjs-proxy-reflect",[604,605,606],"javascript","es6","notes","PInf-V3pY0eCSvHyyd6r2LdFvuPT3RM6rxvoUtneWJs",[609,617,622,627,632,641,652,659,665,675,682,691,696,703,708,714,720,727,734,741,750,756,762,767,772,774,779,784],{"path":610,"title":611,"description":612,"date":613,"category":614,"tags":615},"\u002Fdocs\u002Fbabel-basics","Babel 转译基础与构建集成","Babel 7 的 CLI、preset、plugin、目标环境以及 Gulp、Webpack 和 JSX 转译配置摘录。","2026-09-09","toolchain",[604,605,616,606],"webpack",{"path":618,"title":619,"description":620,"date":613,"category":592,"tags":621},"\u002Fdocs\u002Fes6-arrays-objects","ES6 数组与对象扩展","展开运算符、Array.from、Object.assign、属性描述符与图片预加载示例。",[604,605,606],{"path":623,"title":624,"description":625,"date":613,"category":592,"tags":626},"\u002Fdocs\u002Fes6-basics","ES6 基础：作用域、解构与模板字符串","从课程示例整理 let、const、暂时性死区、全局对象、数组与对象解构及模板字符串。",[604,605,606],{"path":628,"title":629,"description":630,"date":613,"category":592,"tags":631},"\u002Fdocs\u002Fjs-promise-async","Promise、Generator 与 async\u002Fawait","从回调到 Promise 链、组合方法、Generator 执行与 async 错误处理的课程示例整理。",[604,605,606],{"path":633,"title":634,"description":635,"date":636,"category":614,"tags":637},"\u002Fdocs\u002Flinux-commands-cheatsheet","Linux 常用命令与权限管理速查","cp\u002Fmv\u002Frm、目录导航、查找、压缩、网络等基础命令速查，以及 chmod\u002Fchown 的数字与符号写法、常用组合和 WSL 下的坑。","2026-05-28",[638,639,640],"linux","wsl2","cheatsheet",{"path":642,"title":643,"description":644,"date":645,"category":646,"tags":647},"\u002Fdocs\u002Ffrontend-coding-standards","前端团队编码规范","HTML \u002F CSS \u002F JavaScript 三端统一的团队编码约定，含缩进、命名、语法与禁用项，可直接作为 Code Review 依据。","2025-12-17","standards",[648,649,604,605,650,651],"html","css","best-practice","guide",{"path":653,"title":654,"description":655,"date":656,"category":614,"tags":657},"\u002Fdocs\u002Fwindows-mklink","Windows mklink 符号链接用法","mklink 各参数区别与实用场景：目录联接、符号链接与硬链接的选择。","2024-12-18",[658,640],"windows",{"path":660,"title":661,"description":662,"date":663,"category":614,"tags":664},"\u002Fdocs\u002Frandom-color-utils","JS 随机颜色生成方法","几种生成随机 RGB \u002F HEX 颜色的实现方式与各自适用场景。","2024-12-11",[604,640],{"path":666,"title":667,"description":668,"date":669,"category":670,"tags":671},"\u002Fdocs\u002Fcanvas-vs-svg","Canvas 与 SVG 绘图方案选型","对比 Canvas 与 SVG 两种绘图方案的优缺点与适用场景，给出选型判断依据。","2024-12-09","visualization",[672,673,674,650],"canvas","svg","performance",{"path":676,"title":677,"description":678,"date":679,"category":614,"tags":680},"\u002Fdocs\u002Ffree-commercial-fonts","免费可商用字体整理","整理思源黑体、思源宋体等可商用中文字体，规避字体版权风险。","2024-11-03",[681,649,606],"font",{"path":683,"title":684,"description":685,"date":679,"category":686,"tags":687},"\u002Fdocs\u002Finterview-browser-network","浏览器与网络考点","从输入 URL 到页面呈现的完整链路，涵盖渲染流程、回流重绘、HTTP 报文与状态码、跨域同源策略与常见攻击方式。","interview",[688,689,690,674,606],"browser","http","network",{"path":692,"title":693,"description":694,"date":679,"category":686,"tags":695},"\u002Fdocs\u002Finterview-css-layout","CSS 与布局考点","em 与 rem 的区别、移动端三种适配方案对比、viewport 标准设置与 REM 布局的媒体查询实现。",[649,648,650,606],{"path":697,"title":698,"description":699,"date":679,"category":686,"tags":700},"\u002Fdocs\u002Finterview-framework-tooling","框架与工程化考点","React diff 与 setState 机制、Redux 核心组成、Vue 常考清单，以及 Webpack、Vite、Git 的面试要点。",[701,604,616,702,606],"vue","vite",{"path":704,"title":705,"description":706,"date":679,"category":686,"tags":707},"\u002Fdocs\u002Finterview-javascript-core","JavaScript 核心考点","数据类型、this 绑定、闭包、原型链、异步与数组方法，前端面试中 JS 部分的高频考点与代码示例。",[604,605,606],{"path":709,"title":710,"description":711,"date":679,"category":592,"tags":712},"\u002Fdocs\u002Fjs-module-systems","JavaScript 模块化方案","梳理 CommonJS、AMD、ES Module 等模块化方案的差异与使用方式。",[604,713,605,606],"module-system",{"path":715,"title":716,"description":717,"date":679,"category":592,"tags":718},"\u002Fdocs\u002Fwebsocket-basics","WebSocket 基础","WebSocket 全双工通信协议的事件、方法与基本用法整理。",[719,690,604,606],"websocket",{"path":721,"title":722,"description":723,"date":724,"category":614,"tags":725},"\u002Fdocs\u002Fmarkdown-syntax","Markdown 语法速查","Markdown 标题、强调、列表、区块引用、代码、表格、转义与 Mermaid 图表语法整理。","2024-10-18",[726,640,606],"markdown",{"path":728,"title":729,"description":730,"date":731,"category":670,"tags":732},"\u002Fdocs\u002Fgojs-getting-started","GoJS 入门实战","从引入方式、画布初始化到节点模板与数据绑定，一份可直接上手的 GoJS 流程图开发笔记。","2024-08-22",[733,604,606],"gojs",{"path":735,"title":736,"description":737,"date":738,"category":670,"tags":739},"\u002Fdocs\u002Fecharts-options-notes","ECharts 配置项速查","整理 ECharts 常用 option 配置：数据格式、坐标轴、图例与交互项的实际用法。","2024-08-09",[740,604,640],"echarts",{"path":742,"title":743,"description":744,"date":745,"category":614,"tags":746},"\u002Fdocs\u002Fyarn-npm-install-errors","yarn \u002F npm 安装报错处理","yarn 引擎版本不兼容时的 ignore-engines 绕过、Windows 刷新 DNS 解析缓存、npm 缓存清理与校验。","2024-08-06",[747,748,658,749],"npm","nodejs","troubleshooting",{"path":751,"title":752,"description":753,"date":754,"category":670,"tags":755},"\u002Fdocs\u002Fgojs-grid-panel","GoJS 网格面板用法","Diagram.grid 默认网格与网格捕捉、单元格尺寸定制，用 LineH\u002FLineV\u002FBarH\u002FBarV 自定义网格样式，以及把 Grid 面板当作节点元素使用。","2024-07-01",[733,604,606],{"path":757,"title":758,"description":759,"date":760,"category":592,"tags":761},"\u002Fdocs\u002Fhttp-status-codes","HTTP 响应状态码详解","按 1xx 到 5xx 分类梳理 HTTP 状态码的含义与典型使用场景。","2024-06-27",[689,690,640],{"path":763,"title":764,"description":765,"date":593,"category":592,"tags":766},"\u002Fdocs\u002Fes6-functions-classes","ES6 函数与 Class","默认参数、rest、箭头函数的 this、Class 方法、访问器、静态成员与继承。",[604,605,606],{"path":768,"title":769,"description":770,"date":593,"category":614,"tags":771},"\u002Fdocs\u002Fgulp-basics","Gulp 4 任务与文件流","Gulp 任务完成信号、串并行组合、文件流、资源处理、分阶段输出和文件监听。",[604,748,606],{"path":599,"title":5,"description":594,"date":593,"category":592,"tags":773},[604,605,606],{"path":775,"title":776,"description":777,"date":593,"category":614,"tags":778},"\u002Fdocs\u002Fless-basics","Less 语法与编译笔记","变量、嵌套、混合、extend、导入、内置函数和递归生成列的课程示例。",[649,606,640],{"path":780,"title":781,"description":782,"date":593,"category":614,"tags":783},"\u002Fdocs\u002Fwebpack-basics","Webpack 4 配置与开发服务器笔记","课程中的入口出口、loader、plugin、source map、开发代理以及 React 环境配置片段。",[616,604,748,606],{"path":785,"title":786,"description":787,"date":788,"category":592,"tags":789},"\u002Fdocs\u002Fhtml-basics","HTML 基础笔记","HTML 语法规范、常用标签、表格、表单、Canvas 入门与 JavaScript 输出方式速查。","2022-06-10",[648,606,640],1789635934196]