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对象的更多相关文章

  1. 深入理解JS中的对象(三):class 的工作原理

    目录 序言 class 是一个特殊的函数 class 的工作原理 class 继承的原型链关系 参考 1.序言 ECMAScript 2015(ES6) 中引入的 JavaScript 类实质上是 J ...

  2. js中判断对象具体类型

    大家可能知道js中判断对象类型可以用typeof来判断.看下面的情况 <script> alert(typeof 1);//number alert(typeof "2" ...

  3. 浅解析js中的对象

    浅解析js中的对象 原文网址:http://www.cnblogs.com/foodoir/p/5971686.html,转载请注明出处. 前面的话: 说到对象,我首先想到的是每到过年过节见长辈的时候 ...

  4. js中XMLHttpRequest对象实现GET、POST异步传输

    js中XMLHttpRequest对象实现GET.POST异步传输 /* * 统一XHR接口 */ function createXHR() { // IE7+,Firefox, Opera, Chr ...

  5. JavaScript学习12 JS中定义对象的几种方式

    JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工 ...

  6. js中推断对象详细类型

    大家可能知道js中推断对象类型能够用typeof来推断. 看以下的情况 <script> alert(typeof 1);//number alert(typeof "2&quo ...

  7. JavaScript学习12 JS中定义对象的几种方式【转】

    avaScript学习12 JS中定义对象的几种方式 转自:  http://www.cnblogs.com/mengdd/p/3697255.html JavaScript中没有类的概念,只有对象. ...

  8. JS中有关对象的继承以及实例化、浅拷贝深拷贝的奥秘

    一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实 ...

  9. JS中定义对象和集合

    在js中定义对象: 方式一: var obj = {}; obj['a']=1; obj['b']=2; 方式二: var obj=new Object(); obj.a=1; obj.b=2; 在j ...

  10. Js中Map对象的使用

    Js中Map对象的使用 1.定义 键/值对的集合. 2.语法 mapObj = new Map() 3.备注 集合中的键和值可以是任何类型.如果使用现有密钥向集合添加值,则新值会替换旧值. 4.属性 ...

随机推荐

  1. Shell-函数-function

  2. [转帖]解Bug之路-记一次JVM堆外内存泄露Bug的查找

    https://zhuanlan.zhihu.com/p/245401095 解Bug之路-记一次JVM堆外内存泄露Bug的查找 前言 JVM的堆外内存泄露的定位一直是个比较棘手的问题.此次的Bug查 ...

  3. 通过宿主机查看K8S或者是容器内的Java程序的简单方法

    通过宿主机查看K8S或者是容器内的Java程序的简单方法 背景 最近一个项目的环境出现了 cannot create native process 的错误提示 出现这个错误提示时, docker ex ...

  4. Redis scan等命令的学习与研究

    Redis scan等命令的学习与研究 摘要 背景跟前几天说的一个问题类似. 为了验证自己的设想, 所以晚上继续写脚本进行了一轮次的验证. 不过上次讨论时,打击好像都没听懂我说的 所以这次准备从基础开 ...

  5. [百度贴吧]部分CPU的SPEC2006int 结果

    这些测试成绩基本上是本人自己测试的结果.下表中有来自spec官网的两个成绩,因为测试年份较早,系统环境和编译器都较老,测试成绩本人实测的还差,所以仅作为参考.部分测试启用了自动并行和附加的优化库,是为 ...

  6. [转帖]java启动jar包设置启动参数

    目录 一.代码介绍 1.代码: 二.linux命令 1.命令 三.idea本地调试 1.找到Edit Configurations 2.修改Edit Configurations 参数 3.Edit ...

  7. 2024-01-27:用go语言,阿里巴巴走进了装满宝藏的藏宝洞。藏宝洞里面有N堆金币, 第i堆金币的总重量和总价值分别是m[i]、v[i], 阿里巴巴有一个承重量为T的背包,但并不一定有办法将全部的

    2024-01-27:用go语言,阿里巴巴走进了装满宝藏的藏宝洞.藏宝洞里面有N堆金币, 第i堆金币的总重量和总价值分别是m[i].v[i], 阿里巴巴有一个承重量为T的背包,但并不一定有办法将全部的 ...

  8. Similarities:精准相似度计算与语义匹配搜索工具包,多维度实现多种算法,覆盖文本、图像等领域,支持文搜、图搜文、图搜图匹配搜索

    Similarities:精准相似度计算与语义匹配搜索工具包,多维度实现多种算法,覆盖文本.图像等领域,支持文搜.图搜文.图搜图匹配搜索 Similarities 相似度计算.语义匹配搜索工具包,实现 ...

  9. C/C++ MinHook 库的使用技巧

    在上面的各种Hook挂钩方式中,我们都是在手写封装代码,但这样的方式并不高效,真正的生产环境中我们必须使用现成的Hook库,常用的Hook库有免费开源的MinHook和商业的Detours Hook, ...

  10. Win32汇编:汇编版PE结构解析器

    PE格式是Windows系统下最常用的可执行文件格式,有些应用必须建立在了解PE文件格式的基础之上,如可执行文件的加密与解密,文件型病毒的查杀等,熟练掌握PE文件结构,有助于软件的分析. 在PE文件中 ...