Js中Proxy对象
Js中Proxy对象
Proxy对象用于定义基本操作的自定义行为,例如属性查找、赋值、枚举、函数调用等。
语法
const proxy = new Proxy(target, handler);
target: 要使用Proxy包装的目标对象,可以是任何类型的对象,包括原生数组,函数,甚至另一个代理。handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理proxy的行为。
描述
Proxy用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。这个词的原理为代理,在这里可以表示由它来代理某些操作,译为代理器。
var target = {a: 1};
var proxy = new Proxy(target, {
set: function(target, key, value, receiver){
console.log("watch");
return Reflect.set(target, key, value, receiver);
},
get: function(target, key, receiver){
return target[key];
}
});
proxy.a = 11; // watch
console.log(target); // {a: 11}
Object.defineProperty是用于监听属性,而Proxy是监听整个对象,通过调用new Proxy(),可以创建一个代理用来替代另一个对象被称为目标,这个代理对目标对象进行了虚拟,因此该代理与该目标对象表面上可以被当作同一个对象来对待。代理允许拦截在目标对象上的底层操作,而这原本是Js引擎的内部能力,拦截行为使用了一个能够响应特定操作的函数,即通过Proxy去对一个对象进行代理之后,我们将得到一个和被代理对象几乎完全一样的对象,并且可以从底层实现对这个对象进行完全的监控。
// 常见的一道面试题 实现 a===1&&a===2&&a===3 为true
// Object.defineProperty 定义的是属性
// 可以实现对于题目的要求
var _a = 0;
Object.defineProperty(window, "a", {
get:function(){
return ++_a;
}
})
console.log(a===1 && a===2 && a===3); // true
// proxy 代理的是对象
// 因此在调用时实际与题目要求并不太相符
// 但同样也是一种实现方式
var _a = 0;
var proxy = new Proxy(window, {
set: function(target, key, value, receiver){
return Reflect.set(target, key, value, receiver);
},
get: function(target, key, receiver){
if(key === "a") return ++_a;
else return window[key];
}
});
console.log(proxy.a===1 && proxy.a===2 && proxy.a===3); //true
方法
Proxy.revocable()
Proxy.revocable(target, handler)
Proxy.revocable()方法可以用来创建一个可撤销的代理对象,其返回一个包含了代理对象本身和它的撤销方法的可撤销Proxy对象。
target: 将用Proxy封装的目标对象,可以是任何类型的对象,包括原生数组,函数,甚至可以是另外一个代理对象。handler: 一个对象,其属性是一批可选的函数,这些函数定义了对应的操作被执行时代理的行为。
该方法的返回值是一个对象,其结构为{"proxy": proxy, "revoke": revoke},一旦某个代理对象被撤销,它将变得几乎完全不可调用,在它身上执行任何的可代理操作都会抛出TypeError异常,注意可代理操作一共有14种,执行这14种操作以外的操作不会抛出异常。一旦被撤销,这个代理对象便不可能被直接恢复到原来的状态,同时和它关联的目标对象以及处理器对象都有可能被垃圾回收掉。再次调用撤销方法revoke()则不会有任何效果,但也不会报错。
var revocable = Proxy.revocable({}, {
get: function(target, key) {
return `[[ ${key} ]]`;
}
});
var proxy = revocable.proxy;
console.log(proxy.example); // [[ example ]]
revocable.revoke();
// console.log(proxy.example); // 抛出 TypeError
// proxy.example = 1; // 抛出 TypeError
// delete proxy.example; // 抛出 TypeError
// typeof proxy // "object",因为 typeof 不属于可代理操作
handler对象方法
handler对象是一个容纳一批特定属性的占位符对象,它包含有Proxy的各个捕获器trap。所有的捕捉器是可选的,如果没有定义某个捕捉器,那么就会保留源对象的默认行为。
handler.getPrototypeOf():Object.getPrototypeOf方法的捕捉器。handler.setPrototypeOf():Object.setPrototypeOf方法的捕捉器。handler.isExtensible():Object.isExtensible方法的捕捉器。handler.preventExtensions():Object.preventExtensions方法的捕捉器。handler.getOwnPropertyDescriptor():Object.getOwnPropertyDescriptor方法的捕捉器。handler.defineProperty():Object.defineProperty方法的捕捉器。handler.has():in操作符的捕捉器。handler.get(): 属性读取操作的捕捉器。handler.set(): 属性设置操作的捕捉器。handler.deleteProperty():delete操作符的捕捉器。handler.ownKeys():Reflect.ownKeys、Object.getOwnPropertyNames、Object.keys、Object.getOwnPropertySymbols方法的捕捉器。handler.apply(): 函数调用操作的捕捉器。handler.construct():new操作符的捕捉器。
var target = {
a: 1,
f: function(...args){
console.log(...args);
}
};
var proxy = new Proxy(target, {
getPrototypeOf: function(target) {
console.log("getPrototypeOf");
return Object.getPrototypeOf(target);
},
setPrototypeOf: function(target, prototype) {
console.log("setPrototypeOf");
return Object.setPrototypeOf(target, prototype);
},
isExtensible: function(target) {
console.log("isExtensible");
return Object.isExtensible(target);
},
preventExtensions: function(target) {
console.log("preventExtensions");
return Object.preventExtensions(target);
},
getOwnPropertyDescriptor: function(target, prop) {
console.log("getOwnPropertyDescriptor");
return Object.getOwnPropertyDescriptor(target, prop);
},
defineProperty: function(target, prop, descriptor) {
console.log("defineProperty");
return Object.defineProperty(target, prop, descriptor);
},
has: function(target, prop) {
console.log("has");
return prop in target;
},
get: function(target, prop, receiver) {
console.log("get");
return target[prop];
},
set: function(target, prop, value, receiver) {
console.log("set");
target[prop] = value;
return true;
},
deleteProperty: function(target, property) {
console.log("deleteProperty");
delete target[property];
return true;
},
ownKeys: function(target) {
console.log("ownKeys");
return Reflect.ownKeys(target);
}
})
var proxyF = new Proxy(target.f, {
construct: function(target, argumentsList, newTarget) {
console.log("construct");
return new target(...argumentsList);
},
apply: function(target, thisArg, argumentsList) {
console.log("apply");
return target.apply(thisArg, argumentsList);
},
})
const _prototype = {test: 1};
Object.setPrototypeOf(proxy, _prototype); // setPrototypeOf
console.log(Object.getPrototypeOf(proxy)); // getPrototypeOf // { test: 1 }
Object.preventExtensions(proxy); // preventExtensions
console.log(Object.isExtensible(proxy)); // isExtensible // false
Object.defineProperty(proxy, "a", {configurable: true}); // defineProperty
console.log(Object.getOwnPropertyDescriptor(proxy, "a")); // getOwnPropertyDescriptor // { value: 1, writable: true, enumerable: true, configurable: true }
proxy.a = 11; // set
console.log(proxy.a); // get // 11
console.log(Object.keys(proxy)); // ownKeys getOwnPropertyDescriptor getOwnPropertyDescriptor // [ 'a', 'f' ]
delete proxy.a; // deleteProperty
console.log("a" in proxy); // has // false
proxyF(1, 2, 3); // apply 1 2 3
new proxyF(1, 2, 3); // construct 1 2 3
每日一题
https://github.com/WindrunnerMax/EveryDay
参考
https://juejin.im/post/6844903853867925517
https://www.cnblogs.com/kdcg/p/9145385.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Js中Proxy对象的更多相关文章
- 深入理解JS中的对象(三):class 的工作原理
目录 序言 class 是一个特殊的函数 class 的工作原理 class 继承的原型链关系 参考 1.序言 ECMAScript 2015(ES6) 中引入的 JavaScript 类实质上是 J ...
- js中判断对象具体类型
大家可能知道js中判断对象类型可以用typeof来判断.看下面的情况 <script> alert(typeof 1);//number alert(typeof "2" ...
- 浅解析js中的对象
浅解析js中的对象 原文网址:http://www.cnblogs.com/foodoir/p/5971686.html,转载请注明出处. 前面的话: 说到对象,我首先想到的是每到过年过节见长辈的时候 ...
- js中XMLHttpRequest对象实现GET、POST异步传输
js中XMLHttpRequest对象实现GET.POST异步传输 /* * 统一XHR接口 */ function createXHR() { // IE7+,Firefox, Opera, Chr ...
- JavaScript学习12 JS中定义对象的几种方式
JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工 ...
- js中推断对象详细类型
大家可能知道js中推断对象类型能够用typeof来推断. 看以下的情况 <script> alert(typeof 1);//number alert(typeof "2&quo ...
- JavaScript学习12 JS中定义对象的几种方式【转】
avaScript学习12 JS中定义对象的几种方式 转自: http://www.cnblogs.com/mengdd/p/3697255.html JavaScript中没有类的概念,只有对象. ...
- JS中有关对象的继承以及实例化、浅拷贝深拷贝的奥秘
一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实 ...
- JS中定义对象和集合
在js中定义对象: 方式一: var obj = {}; obj['a']=1; obj['b']=2; 方式二: var obj=new Object(); obj.a=1; obj.b=2; 在j ...
- Js中Map对象的使用
Js中Map对象的使用 1.定义 键/值对的集合. 2.语法 mapObj = new Map() 3.备注 集合中的键和值可以是任何类型.如果使用现有密钥向集合添加值,则新值会替换旧值. 4.属性 ...
随机推荐
- PHPCMS V9安装出现DNS解析失败的解决方法-不支持采集和保存远程图片
目前因为phpcms官网停止解析后,很多人安装phpcms v9出现如下错误: 这是因为检测dns解析的域名是phpcms官网的域名,官网域名停止解析后肯定检测失败.解决方法如下: 打开/ ...
- 单元测试中如何Mock HttpContext
最近团队有小伙伴问在单元测试中如何Mock HttpContext. 这是一个好问题,整理了一个实现方案分享给大家. 在C#中,尤其是在单元测试场景下,模拟(Mocking)HttpContext 是 ...
- MySQL调优学习-快速获取占用CPU较高的SQL语句
MySQL调优学习-快速获取占用CPU较高的SQL语句 背景 早上突然发现一个MySQL数据库的CPU使用率居高 因为是一个混布的环境上面还有一个redis 怕影响业务就上去像查看一下具体是何种原因导 ...
- [转帖]Oracle客户端与Oracle数据库兼容矩阵
https://www.cnblogs.com/kerrycode/p/17666025.html Oracle客户端与Oracle数据库之间是有兼容支持关系的,有些低版本的Oracle Client ...
- [转帖]TiKV & TiFlash 加速复杂业务查询丨TiFlash 应用实践
返回全部 边城元元案例实践2022-08-02 复杂业务查询对于传统的关系型数据库来说是一种考验,而通过 TiKV 行存与 TiFlash 的列存结合使用就能很好地应对.本文根据 TUG 用户边城元元 ...
- [转帖]探索惊群 ④ - nginx - accept_mutex
https://wenfh2020.com/2021/10/10/nginx-thundering-herd-accept-mutex/ 由主进程创建的 listen socket,要被 fork ...
- RabbitMQ 测试环境的简单创建于使用 permission vhost 以及 权限简单设置
之前用docker运行起来 rabbitmq的容器了 但是今天发现有问题. 简单沟通了下 需要进行处理. 方法主要是如下 1. 运行容器: docker run --name rabbitmq -ti ...
- bean的一生
你曾读spring源码 "不知所云"."绞尽脑汁"."不知所措"嘛 那这篇文章可能会对你有所帮助,小编尝试用简单.易懂的例子来模拟sprin ...
- el-dialog组件无法跟新视图上的数据
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%"> ...
- VS2013未能正确加载microsoft.visualstudio.editor.implementation.editorpackage
在用VS2013做项目,但是特别不顺利,这不,VS2013突然罢工了,连解决方案都打不开了,会出现如下的错误: 试了网上的各种解决方案,总算找到一个适合自己的,具体方法如下: 1.打开VS2013的& ...