网站首页 > 技术文章 正文
前言
今天面试的时候面试官叫我聊聊代理是怎么一回事儿,我支支吾吾磨磨蹭蹭就蹦出来了一个proxy,然后还有一个Object.defineProperty,剪不断理还乱,脑子里就像毛线打结一样思维缠绕,到底是怎么一回事儿,今天就写篇文章搞定他。
代理
代理是es6中的新特性,它可以在不修改原对象代码的情况下,控制对原对象的访问,这为JavaScript编程带来了更大的灵活性和控制能力。他可以实现对对象的拦截和自定义操作,比如属性查找、赋值、枚举、函数调用等。
在es5中没有代理这个操作,但是某些机制可以实现类似代理的操作,虽然没有像es6中的代理那么灵活,但是在一些简单的场景下可以使用。
在es5中如何模拟代理
可以通过一些间接的方式模拟代理的行为,但这通常会更复杂且不够灵活
- 使用闭包
你可以通过闭包,在外部函数里面定义变量,在get和set方法里面引用这个变量,并且做一些额外的逻辑,返回get和set方法。
function createCounter (){
let _count = 0;
return {
getCount: function(){
//当访问这个变量时可以做额外的逻辑
console.log('get');
return _count;
},
setCount(num){
//当修改这个变量时可以做额外的逻辑
console.log('set');
_count = num;
},
}
}
const counter = createCounter();
console.log(counter.getCount());
counter.setCount(10);
2.使用闭包和对象字面量 你可以通过闭包来封装对目标对象的访问,并在访问时执行额外的逻辑。
var obj = {
_value: null,
get value() {
//当访问这个变量时可以做额外的逻辑
console.log('get');
return this._value;
},
set value(newValue) {
//当修改这个变量时可以做额外的逻辑
console.log('set');
this._value = newValue;
}
};
console.log(obj.count);//get 0
obj.count = 10;// set
3.使用Object.defineProperty
Object.defineProperty 方法允许你精确地添加或修改对象的属性。你可以使用它来定义getter和setter,这与在对象字面量中定义它们类似,但提供了更多的灵活性和控制能力,因为它提供了一些属性来约束目标对象的属性,接下里是相关语法特性。
语法
Object.defineProperty(obj, prop, descriptor)
- obj:要定义属性的对象。
- prop:要定义或修改的属性的名称或Symbol。
- descriptor:将被定义或修改的属性描述符。
属性描述符
value:属性的值。
writable:当且仅当该属性的writable为true时,属性的值才能被赋值运算符改变。默认为false
enumerable:当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为false。换句话说,当使用for...in循环、Object.keys()方法、JSON.stringify()方法(除非属性值的原始值为undefined、函数、或symbol类型的键)等枚举对象属性的方法时,该属性会被包括在内。
configurable:当且仅当该属性的configurable为true时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为false。
get:一个给属性提供getter的方法,如果没有getter则为undefined。当访问该属性时,会调用此getter函数,执行时不传入任何参数,但是会传入this对象(由于函数绑定,this可能是调用对象本身)。
set:一个给属性提供setter的方法,如果没有setter则为undefined。当属性值被修改时,会调用此setter函数。该方法将接受唯一参数,即被赋予的新值。
如何使用Object.defineProperty模拟代理
var obj = {};
Object.defineProperty(obj, 'value', {
get: function() {
console.log('get');
return this._value;
},
set: function(newValue) {
console.log('set');
this._value = newValue;
},
enumerable: true, //该属性可枚举
configurable: true //该属性可配置
});
es6中的代理 Proxy
在es6中创建代理是通过构造函数来实现的。
const proxy = new Proxy(target,handler)
它接受两个参数:目标对象(target)和一个处理对象(handler),后者定义了要拦截并自定义的行为。
常见的handler对象中的拦截行为有:
- get(target, propKey, receiver):拦截对属性的读取操作。
- set(target, propKey, value, receiver):拦截对属性的赋值操作。
- has(target, propKey):拦截propKey in proxy的操作。
- deleteProperty(target, propKey):拦截delete proxy[propKey]的操作。
- ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环、Object.values()和Object.entries()操作。
- apply(target, thisArg, argumentsList):拦截函数的调用。
- construct(target, args, newTarget):拦截new操作符。
示例
let obj = {}
let handler = {
get(target, key, receiver) {
console.log('get');
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
console.log('set');
return Reflect.set(target, key, value, receiver);
}
}
const proxy = new Proxy(obj, handler);
proxy.count = 10;
console.log(proxy.count);
使用Reflect
在编写代理的捕获器时,通常会用到Reflect对象。ReflectAPI中的方法与捕获器一一对应,提供了一种更直接的方式来调用目标对象上的方法。使用Reflect可以让代码更简洁、易于理解,同时也避免了直接操作对象可能带来的问题(如直接调用target[propKey]可能触发另一个代理的捕获器)。
应用场景
代理在JavaScript中有很多应用场景
数据绑定:在vue中,代理就被用于实现数据绑定和响应式系统
权限控制:在对象中的属性被访问时进行权限判断
记录日志:在对象被访问时记录日志
注意事项
- 代理主要用于操作对象,不能代理基本数据类型(如Number、String等)。
- 代理的性能通常会比直接操作目标对象稍差,因为每次操作都需要经过捕获器的处理。
- 代理的捕获器必须返回一个与操作类型相符的值(例如,get捕获器应该返回属性值),否则可能会导致意外的行为。
猜你喜欢
- 2025-06-13 Linux 上利用Nginx代理uWSGI处理Flask web应用
- 2025-06-13 如何隐藏代理器服务地址?企业级IP匿名化与反追踪技术
- 2025-06-13 宝塔面板使用Nginx反向代理解决跨域问题
- 2025-06-13 海尔集团武汉中心总经理孙梁君——以智慧家电 升级品质生活
- 2025-06-13 给小白的 Nginx 10分钟入门指南(nginx入门教程)
- 2025-06-13 反向代理以及其使用场景(反向代理啥意思)
- 2025-06-13 Vue炼金术:解锁前端开发的进阶之道
- 2025-06-13 93.8k Star 的内网穿透神器 frp:DIY开发者必备的反向代理
- 2025-06-13 Nginx正向代理、反向代理、负载均衡及性能优化
- 2025-06-13 深入理解跨域及常见误区揭秘(深入理解跨域及常见误区揭秘论文)
你 发表评论:
欢迎- 523℃Oracle分析函数之Lag和Lead()使用
- 520℃几个Oracle空值处理函数 oracle处理null值的函数
- 517℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 504℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 501℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 493℃【数据统计分析】详解Oracle分组函数之CUBE
- 472℃Oracle有哪些常见的函数? oracle中常用的函数
- 471℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端富文本编辑器 (47)
- 前端路由 (61)
- 前端数组 (73)
- 前端排序 (47)
- 前端定时器 (47)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)