爬虫&逆向--Day10--Proxy代理机制
一、Proxy代理机制
1.1、概念
JavaScript中的Proxy是一种内置对象,它允许你在访问或操作对象之前拦截和自定义底层操作的行为。通过使用Proxy,你可以修改对象的默认行为,添加额外的逻辑或进行验证,以实现更高级的操作和控制。
Proxy对象包装了另一个对象(目标对象),并允许你定义一个处理程序(handler)来拦截对目标对象的操作。处理程序是一个带有特定方法的对象,这些方法被称为"捕获器"(traps),它们会在执行相应的操作时被调用。
1.2、代理操作
//创建一个将要被代理的对象 var User = { username: "bobo", age: 20 } //创建代理对象,Proxy的参数1:被代理对象。参数2:处理器 user_1 = new Proxy(User, { // target 被代理对象,其实就是User user_1是代理对象 // p 被代理对象的内部成员(属性) get(target, p) { console.log(`获取属性${p}操作`) //返回被代理对象的p属性值 // Reflect.get用于设置对象属性值的机制 return Reflect.get(target, p); }, set(target, p, value) { console.log(`设置属性${p}操作`) //Reflect是一个用于设置对象属性值的机制 Reflect.set(target, p, value); } }); console.log(user_1.username); /* 获取属性username操作 bobo */ console.log(user_1.age); /* 获取属性age操作 20 */ user_1.username = "Jay" user_1.age = 18 console.log(user_1.username); console.log(user_1.age); /* 设置属性username操作 设置属性age操作 获取属性username操作 Jay 获取属性age操作 18 */
//创建一个将要被代理的对象 var User = { username: "bobo", age: 20 } //创建代理对象,Proxy的参数1:被代理对象。参数2:处理器 user_1 = new Proxy(User, { // target 被代理对象,其实就是User user_1是代理对象 // p 被代理对象的内部成员(属性) get(target, p) { console.log(`获取属性${p}操作`) //返回被代理对象的p属性值 // Reflect.get用于设置对象属性值的机制 return Reflect.get(target, p); }, set(target, p, value) { console.log(`设置属性${p}操作`) //Reflect是一个用于设置对象属性值的机制 Reflect.set(target, p, value); } }); console.log(user_1.username); console.log(user_1.age); console.log(user_1.address); /* 获取属性username操作 bobo 获取属性age操作 20 获取属性address操作 undefined */
1.3、
var Stu = { "name": "小明" }; //通过属性描述符获取Stu对象中的name属性值 console.log(Object.getOwnPropertyDescriptor(Stu, "name").value); // 小明
那么,这个时候我们该如何通过代理去监控通过属性描述符对属性进行的操作行为呢?(拦截获取属性描述符)
//创建user对象 var User = { username: "bobo", age: 20, address:"Bj" } user_1 = new Proxy(User, { get(target, p) { console.log(`获取属性${p}操作`) return Reflect.get(target, p); }, set(target, p, value) { console.log(`设置属性${p}操作`) Reflect.set(target, p, value); }, getOwnPropertyDescriptor(target, p){ let result; result = Reflect.getOwnPropertyDescriptor(target, p); console.log(`通过属性描述符获取属性${p}操作`) return result; } }); //测试 console.log(user_1.username); // 通过普通的方式获取被代理对象的值 /* 获取属性username操作 bobo */ user_1.age = 30; // 通过普通的方式设置被代理对象的值 console.log(user_1.age); /* 设置属性age操作 获取属性age操作 30 */ console.log(Object.getOwnPropertyDescriptor(user_1, "address").value); /* 通过属性描述符获取属性address操作 Bj */
-
defineProperty对象属性的定义
// 通过属性描述符给被代理对象User对象定义一个sex属性 Object.defineProperty(user_1, 'sex', { value: 'man', writable: true, // 允许修改属性值 enumerable: true, // 允许枚举属性 configurable: true // 允许删除或修改属性描述符 } ); // 通过属性描述符设置属性sex操作
那么,这个时候我们该如何通过代理去监控通过属性描述符对属性进行的定义行为呢?(拦截属性定义)
//创建user对象 var User = { username: "bobo", age: 20, address:"Bj" } user_1 = new Proxy(User, { get(target, p) { console.log(`获取属性${p}操作`) return Reflect.get(target, p); }, set(target, p, value) { console.log(`设置属性${p}操作`) Reflect.set(target, p, value); }, getOwnPropertyDescriptor(target, p){ let result; result = Reflect.getOwnPropertyDescriptor(target, p); console.log(`通过属性描述符获取属性${p}操作`) return result; }, defineProperty(target, p, attributes) { console.log(`通过属性描述符设置属性${p}操作`) let result; result = Reflect.defineProperty(target, p, attributes); return result; } /* attributes参数通常与属性描述符(Property Descriptor)相关。属性描述符是一个对象,它定义了属性的特性, 如是否可写、可枚举、可配置等。在defineProperty方法中,attributes参数就是用来指定这些特性的。 或者简单讲,attributes是一个对象,它包含了要定义或修改的属性的特性 */ }); //测试 console.log(user_1.username); // 通过普通的方式获取被代理对象的值 /* 获取属性username操作 bobo */ user_1.age = 30; // 通过普通的方式设置被代理对象的值 console.log(user_1.age); /* 设置属性age操作 获取属性age操作 30 */ console.log(Object.getOwnPropertyDescriptor(user_1, "address").value); /* 通过属性描述符获取属性address操作 Bj */ // 通过属性描述符给被代理对象User对象定义一个sex属性 Object.defineProperty(user_1, 'sex', { value: 'man', writable: true, // 允许修改属性值 enumerable: true, // 允许枚举属性 configurable: true // 允许删除或修改属性描述符 } ); // 通过属性描述符设置属性sex操作 /* 因此后期在进行代理操作的时候,以上的四个函数都必须全部写出来,因为不确定JS代码是 通过常规的方式设置的还是通过属性描述符设置的 */
1.4、
Add = function(a,b){ console.log("Add函数正在被调用"); return a+b; } add = new Proxy(Add, { /* target:被代理对象 thisArg:是一个函数指针,就等同于this argList:函数的参数 a b */ apply:function (target, thisArg, argList){ // target: 函数对象。thisArg: 调用函数的this指针。argList:函数参数数组 let result; result = Reflect.apply(target, thisArg, argList); console.log(`${target.name}函数被调用,参数为:${argList}`); return result; } }); add(1,2); /* Add函数正在被调用 Add函数被调用,参数为:1,2 */
1.5、
// function Animal() { this.name = "mini"; this.age = 20 } //对象被创建的监控:如何监控对象被创建的行为 // 创建一个代理对象:专门监控被代理对象是否被实例化 Animal_proxy = new Proxy(Animal, { // target, 被代理对象 // argArray 参数列表 // newTarget 可选参数,不写也可以 // construct:function (target, argArray, newTarget) { construct: function (target, argArray) { console.log('对象被创建'); console.log(`${target.name}函数被调用,参数为:${argArray}`); let ret = Reflect.construct(target, argArray); return ret; } } ) // 实例化一个对象:调用对象的构造方法 // animal = new Animal() animal = new Animal_proxy() /* 对象被创建 Animal函数被调用,参数为: */
// 扩展一、 function People(name, age) { this.name = name; //this表示对象的调用者 this.age = age; this.chi = function () { console.log(this.name, "在吃东西") } } people = new Proxy(People, { get(target, p) { console.log(`获取属性${p}操作`) return Reflect.get(target, p); }, set(target, p, value) { console.log(`设置属性${p}操作`) //Reflect是一个用于设置对象属性值的机制 Reflect.set(target, p, value); }, apply: function (target, thisArg, argList) { let result = Reflect.apply(target, thisArg, argList); console.log(`${target.name}函数被调用,参数为:${argList}`); return result; }, construct: function (target, argArray, newTarget) { let result = Reflect.construct(target, argArray, newTarget); console.log(`${target.name}函数被调用--1,参数为:${argArray}`); return result; } }) // p1 = new People("alex", 18); // p1.chi(); p2 = new people("wusir", 18); p2.chi(); /* Constructor names usually start with an uppercase letter. A typo? 构造函数名称通常以大写字母开头。拼写错误? 获取属性prototype操作 People函数被调用--1,参数为:wusir,18 wusir 在吃东西 */
//扩展二、 var Person = { name : "alvin", age : 18, say: function(){ console.log("say---被打印了") } }; // console.log(Person.say()) people = new Proxy(Person, { get(target, p) { console.log(`获取属性${p}操作`) return Reflect.get(target, p); }, set(target, p, value) { console.log(`设置属性${p}操作`) //Reflect是一个用于设置对象属性值的机制 Reflect.set(target, p, value); }, apply: function (target, thisArg, argList) { let result = Reflect.apply(target, thisArg, argList); console.log(`${target.name}函数被调用,参数为:${argList}`); return result; }, construct: function (target, argArray, newTarget) { let result = Reflect.construct(target, argArray, newTarget); console.log(`${target.name}函数被调用--1,参数为:${argArray}`); return result; } }) console.log(people.say()) /* 获取属性say操作 say---被打印了 undefined */

浙公网安备 33010602011771号