0

0

深入浅析ES6中的Proxy(代理)

青灯夜游

青灯夜游

发布时间:2021-07-05 11:23:25

|

1988人浏览过

|

来源于掘金社区

转载

深入浅析ES6中的Proxy(代理)

创建一个简单的Proxy

let target = {}
let proxy = new Proxy(target, {})

proxy.name = 'proxy'

console.log(proxy.name) // proxy
console.log(target.name) // proxy

target.name = 'target'

console.log(proxy.name) // target
console.log(target.name) // target

这个实例将"proxy"赋值给proxy.name属性时会在目标上创建name,代理只是简单的将操作转发给目标,他不会储存这个属性。相当于proxy.name和target.name引用的都是target.name的值。

使用set陷阱验证属性

set陷阱接收四个参数:

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

3.value:被写入的属性值

4.receiver:操作发生的对象(通常是代理)

let target = {
    name: "target"
}

let proxy = new Proxy(target, {
    set(trapTarget, key, value, receiver) {
        if (!trapTarget.hasOwnProperty(key)) {
            if (isNaN(value)) {
                throw new TypeError("属性必须时数字")
            }
        }

        return Reflect.set(trapTarget, key, value, receiver)
    }
})

proxy.count = 1
console.log(proxy.count) //1
console.log(target.count) //1

proxy.name = "proxy"

console.log(proxy.name) //proxy
console.log(target.name) //proxy

proxy.other = "other" // 这里会报错因为不数字

这个实例每次在外面改变proxy的值时就会出发set函数。

用get陷阱验证对象结构

get接收3个参数

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

3.receiver:操作发生的对象(通常是代理)

let proxy = new Proxy({}, {
    get(trapTarget, key, receiver) {
        if (!(key in receiver)) {
            throw new TypeError("属性" + key + "不存在")
        }

        return Reflect.get(trapTarget, key, receiver)
    }
})

proxy.name = "proxy"

console.log(proxy.name) //proxy

console.log(proxy.age) // 属性不存在会抛出错误

当我们访问proxy创建的对象属性时就会触发get方法

使用has陷阱因此已有属性

has接收2个参数:

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

let target = {
    name: "target",
    value: 42
}

let proxy = new Proxy(target, {
    has(trapTarget, key) {
        if (key === 'value') {
            return false
        } else {
            return Reflect.has(trapTarget, key)
        }
    }
})


console.log("value" in proxy) // false
console.log("name" in proxy) // true
console.log("toString" in proxy) // true

用deleteProperty陷阱防止删除属性

deleteProperty接收2个参数:

寻鲸AI
寻鲸AI

寻鲸AI是一款功能强大的人工智能写作工具,支持对话提问、内置多场景写作模板如写作辅助类、营销推广类等,更能一键写作各类策划方案。

下载

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

let target = {
    name: "target",
    value: 42
}

let proxy = new Proxy(traget, {
    deleteProperty(trapTarget, key) {
        if (key === "value") {
            return false
        } else {
            return Reflect.deleteProperty(trapTarget, key)
        }
    }
})


console.log("value" in proxy) // true

let result1 = delete proxy.value

console.log(result1) // false
console.log("value" in proxy) // true

console.log("name" in proxy) // true

let result2 = delete proxy.name
console.log(result2) // true
console.log("name" in proxy) // false

当外部要删除proxy的属性就会触发deleteProperty函数

原型代理陷阱(setProptotypeOf,getPrototypeOf)

setProptotypeOf接收2个参数

1.trapTarget:用于接收属性(代理的目标)的对象

2.proto:作为原型使用的对象

let target = {}

let proxy = new Proxy(target, {

    // 访问时调用
    getPrototypeOf(trapTarget) {
        return null
    },
    // 改变时调用
    setPrototypeOf(trapTarget, proto) {
        return false
    }

})

let targetProto = Object.getPrototypeOf(target)
let proxyProto = Object.getPrototypeOf(proxy)

console.log(targetProto === Object.prototype) //true
console.log(proxyProto === Object.prototype) // false
console.log(proxyProto) // null

Object.setPrototypeOf(target, {}) // 成功

Object.setPrototypeOf(proxy, {}) // 抛出错误

如果正常实现

let target = {}

let proxy = new Proxy(target, {

    // 访问时调用
    getPrototypeOf(trapTarget) {
        return Reflect.getPrototypeOf(trapTarget)
    },
    // 改变时调用
    setPrototypeOf(trapTarget, proto) {
        return Reflect.setPrototypeOf(trapTarget, proto)
    }

})

let targetProto = Object.getPrototypeOf(target)
let proxyProto = Object.getPrototypeOf(proxy)

console.log(targetProto === Object.prototype) //true
console.log(proxyProto === Object.prototype) // true

Object.setPrototypeOf(target, {}) // 成功

Object.setPrototypeOf(proxy, {}) // 成功

属性描述符陷阱

defineProperty接收三个参数:

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

3.descriptor:属性的描述对象

let proxy = new Proxy({}, {
    defineProperty(trapTarget, key, descriptor) { // descriptor 只能接收enumerable, configurable, value, writeable, get, set 
        if (typeof key === "symbol") {
            return false
        }
        return Reflect.defineProperty(trapTarget, key, descriptor)
    },
    getOwnPropertyDescriptor(trapTarget, key) {
        return Reflect.getOwnPropertyDescriptor(trapTarget, key)
    }
})

Object.defineProperty(proxy, "name", {
    value: "proxy"
})

console.log(proxy.name) //proxy

let nameSymbol = Symbol("name")

Object.defineProperty(proxy, nameSymbol, {
    value: "proxy"
})

在外部调用defineProperty | getOwnPropertyDescriptor时会触发内部definenProperty | getOwnPropertyDescriptor方法。

ownKeys陷阱

ownKeys陷阱会拦截外部的Object.keys(),Object.getOwnPropertyName(),Object.getOwnPropertySymbols()和Object.assign()四个方法

let proxy = new Proxy({}, {
    ownKeys(trapTarget) {
        return Reflect.ownKeys(trapTarget).filter(key => {
            return typeof key !== "string" || key[0] !== '_'
        })
    }
})

let nameSymbol = Symbol("name")

proxy.name = "proxy"

proxy._name = "private"

proxy[nameSymbol] = "symbol"

let names = Object.getOwnPropertyNames(proxy),
    keys = Object.keys(proxy),
    symbols = Object.getOwnPropertySymbols(proxy)

console.log(names.length) // 1
console.log(names) // name

console.log(keys.length) //1
console.log(keys[0]) // name

console.log(symbols.length) //1
console.log(symbols[0]) // symbol(name)

更多编程相关知识,请访问:编程入门!!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
es6新特性
es6新特性

es6新特性有:1、块级作用域变量;2、箭头函数;3、模板字符串;4、解构赋值;5、默认参数;6、 扩展运算符;7、 类和继承;8、Promise。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

97

2023.07.17

es6新特性有哪些
es6新特性有哪些

es6的新特性有:1、块级作用域;2、箭头函数;3、解构赋值;4、默认参数;5、扩展运算符;6、模板字符串;7、类和模块;8、迭代器和生成器;9、Promise对象;10、模块化导入和导出等等。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

188

2023.08.04

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

221

2025.12.24

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1497

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

623

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

592

2024.03.22

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

25

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.1万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号