JavaScript红宝书第九章:代理与反射

这篇具有很好参考价值的文章主要介绍了JavaScript红宝书第九章:代理与反射。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

本文主要讲解代理与反射,那么好,本文正式开始。

代理

代理基础

代理是目标对象的替身,同时它又独立于目标对象,意思就是说,我们在操作对象的时候,直接操作或通过操作代理的方式间接操作目标对象。

创建空代理

使用proxy构造函数创建代理,proxy有两个必要参数:
1,目标对象。2.处理程序
语法格式:const proxyObj=new Proxy(target,handle)
举例:

			const obj={id:"target"};
			const handle={}
			const proxy=new Proxy(obj,handle)
			console.log(obj.id,proxy.id);//target target
			
			obj.id='tar'
			console.log(obj.id,proxy.id);//tar tar
			
			console.log(obj.hasOwnProperty('id'),proxy.hasOwnProperty('id'));//true true
			
			// console.log(obj instanceof object,proxy instanceof Proxy);
			
			console.log(obj===proxy);//false

在上述代码中,实现了一个简单的代理,这里用的程序处理handle为空,我们既可以用obj.id也可以用proxy.id都能得到target这个值。

可以用hasOwnProperty检测出对象的具体属性

Proxy.prototypeundefined,因为 Proxy 是一个构造函数,它的原型对象是通过 Object.create(null) 创建的。这意味着 Proxy.prototype 没有继承自任何其他对象,因此它是独立的。

可以用严格相等检测出代理和目标对象的不同。

定义捕获器

捕获器是代理的重要概念之一,它作用是可以在设置捕获的某个路径中进行程序处理。实现捕获。
举例:比如我们想要让目标对象输出时候输出1.

const obj={id:"target"}
const handle={
	get(){
		return 1;
	}
}
const proxy=new Proxy(obj,handle)
console.log(obj.id,proxy.id);//target 1

捕获器参数和反射API

每个捕获器都有参数,这里拿get举例,get捕获器有三个参数:
1.目标对象2.要查询属性3.代理对象
那么我们就可以基于它的这些参数特性,去二次封装它们的捕获器。

const obj={id:'target'}
		const handle={
			get(target,prototype,proxy){
				console.log(target === obj);//true
				console.log(prototype);// id
				console.log(proxy);//Proxy(Object) {id: 'target'}
				return 1;
			}
		}
		const proxy=new Proxy(obj,handle)
		console.log(proxy.id);

当我们知道一个捕获器的原始参数后,就可以封装,如果我们不知道原始参数时,可以用到全局Reflect方法,Reflect有和被拦截方法相同的名称和行为。

const obj={id:'target'}
const handle={
	get(){
		return Reflect.get(...arguments)
	}
}
const simplehandle={
	get:Reflect.get
}
const proxy=new Proxy(obj,handle)
const simpleProxy=new Proxy(obj,simplehandle)
const bestProxy=new Proxy(obj,Reflect)

console.log(proxy.id,simpleProxy.id,bestProxy.id);//target target target

捕获器不变式

捕获器为了避免出现过于反常行为,引入了不变式的概念。在使用程序处理中,必须遵循不变式的条件。否则将报错,比如目标对象有一个不可配置且不可写的属性,捕获器返回一个不同值时,报错TypeError。

const obj={}
			Object.defineProperty(obj,'id',{
				configurable:false,
				writable:false,
				value:'target'
			})
			const handle={
				get(){return 'tar'}
			}
			const proxy=new Proxy(obj,handle)
			console.log(proxy.id);//Uncaught TypeError: 

可撤销代理

为了让代理有足够自由度,同时我们也可以通过revocable()函数实现对代理的撤销,撤销后,代理将失去它原有的作用。

const obj={id:"target"}
const handle={
	get(){return 'tar'}
}
const {proxy,revoke}=Proxy.revocable(obj,handle)
console.log(proxy.id);//tar
revoke()
console.log(proxy.id);//ncaught TypeError: Cannot perform 'get' on a proxy that has been revoked

实用反射API

  1. 反射API与对象API
  • 反射API不限于只应用在捕获程序中。
  • 大多数反射API方法在Object类型中都有对应的方法。
  1. 反射API方法部分有状态标记,也就是说它能判断是否生效。
     Reflect.defineProperty()
     Reflect.preventExtensions()
     Reflect.setPrototypeOf()
     Reflect.set()
     Reflect.deleteProperty()
    以上方法都提供状态标记。

代理另一个代理

可以通过一个双重代理来代理目标对象,也就是经过两次程序处理。
举例:

const obj={id:'target'}
const handle={
	get(){
		console.log('first');
		return Reflect.get(...arguments);
	}
}
const firstProxy=new Proxy(obj,handle)

const secondHandle={
	get(){
		console.log('second');
		return Reflect.get(...arguments);
	}
}
const secondProxy=new Proxy(firstProxy,secondHandle);
console.log(secondProxy.id);//second first target

反射

代理捕获器与反射方法

代理可以捕获13中不同操作。

get()

get方法会在获取属性值时被调用,对应的反射方法是Reflect.get()
语法格式:Reflect.get(proxy, property, receiver)

set()

set方法会在更新属性值时被调用,对应的反射方法是Reflect.set()
语法格式:Reflect.set(proxy, property, value, receiver)

has()

has方法会在in操作符中被调用,主要判断左侧属性是否在右侧对象中,对应的反射方法是Reflect.has()

const obj={id:'target'}
const handle={
	has(){
		console.log('has()');
		return Reflect.has(...arguments)
	}
}
const proxy=new Proxy(obj,handle)
console.log('id' in proxy);//has() true

还有像defineProperty、getOwnPropertyDescriptor、deleteProperty、ownKeys、getPrototypeOf、setPrototypeOf、isExtensible、preventExtensions、apply、construct等方法,这里就不一一赘述了,这些方法都可以被捕获(劫持)并且可以二次封装。

代理模式

跟踪属性访问

可以监控属性何时或何处被访问,可以通过劫持get、set或has方法来实现,举例:

const obj={id:'target'}
const handle={
	get(target,a,proxy){
		console.log("被调用",a);
		return Reflect.get(...arguments);
	}
}
const proxy=new Proxy(obj,handle)
console.log(proxy.id);// 被调用 id target

隐藏属性

可以通过数据劫持后判断是否显示某个属性,如果不显示,则实现隐藏效果。举例:

const obj={id:'target',age:18}
const hidden=['age']

const handle={
	get(target,a,proxy){
		if(hidden.includes(a)){
			return undefined;
		}else{
			return Reflect.get(...arguments)
		}
	},
	has(target,a,proxy){
		if(hidden.includes(a)){
			return false;
		}else{
			return Reflect.get(...arguments)
		}
	}
}
const proxy=new Proxy(obj,handle)
console.log(proxy.id,proxy.age);//target undefined
console.log('id' in proxy,'age' in proxy);//true false

属性验证

可以判断验证属性格式是否正确,举例:

const obj={age:18}
const handle={
	set(target,property,value){
		if(typeof value!=='number'){
			return false;
		}else{
			return Reflect.set(...arguments);
		}
	}
}
const proxy=new Proxy(obj,handle)
proxy.age='1'
console.log(proxy.age);//18
proxy.age=1
console.log(proxy.age);//1

数据绑定

可以把一个数据绑定到另一个数据中,实现强关联。举例:

const arr=[]

class user{
	constructor(name){
		this.name_=name
	}
}

const handle={
	construct(){
		const newUser=Reflect.construct(...arguments);
		arr.push(newUser);
		return newUser;
	}
}

const proxy=new Proxy(user,handle);
new proxy('Hellon');
console.log(arr);//[user]

总结

代理就是对数据的劫持,并且劫持的过程中加一些操作,反射,就是对象方法的复制API。可以从头到尾复刻对象的某个API方法。以上就是,全部内容。文章来源地址https://www.toymoban.com/news/detail-764471.html

到了这里,关于JavaScript红宝书第九章:代理与反射的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构第九章

    (1)顺序表的查找          1)顺序表查找的结构 顺序查找的过程:从表中最后一个记录开始,逐个进行记录的和给定值的比较。(也就是说,在查找到时候从最后一个元素开始查找,在这个表中位置为0的位置空着,留给你要查找的元素) 在顺序表的查找中,需要

    2024年01月21日
    浏览(41)
  • 第九章 Gitlab使用

    微服务项目,常常需要多人协作完成工作,本章教程是介绍Gitlab使用,使多人协作告别低端的手动拷贝,也告别传统的SVN。 https://git-scm.com/download/win ssh-keygen -t rsa -C “zhangsan@163.com” -b 4096 cat ~/.ssh/id_rsa.pub | clip 打开git bash窗口 定位到要上传的目录 初始化 将当前目录添加到

    2024年01月18日
    浏览(52)
  • mysql 第九章

    目录 1.mha 搭建  2.总结 主从同步: 安装 mha 软件:  mha 模拟 vip 飘移、master 切换:         mha  是一套优秀的 mysql 高可用环境下故障切换和主从复制的软件。mha 解决 mysql 单点的问题。mysql 故障切换过程中,mha 能做到 0-30 秒内自动完成故障切换操作。mha 能在故障切换的过

    2024年02月16日
    浏览(42)
  • 【OpenCV】第九章: 图像梯度

    第九章: 图像梯度 图像梯度是用来做 边缘检测 的一种方法。 为什么要检测边缘? 比如自动驾驶里面,我们至少要做的一个工作就是道路的边缘检测,只有正确的检测到道路的边缘我们的车才会行驶在道路上而不是开到马路牙子外。 或者从另一个角度解释,我们做边缘检测

    2024年01月24日
    浏览(38)
  • C国演义 [第九章]

    力扣链接 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票) 示例 1: 输入:prices = [3,3,5,0,0,3,1,4] 输出:6 解释:

    2024年02月16日
    浏览(29)
  • 第九章 更复杂的光照

    Unity的渲染路径 渲染路径决定了光照是如何应用到Unity Shader中的, 需要为每个Pass指定它的渲染路径 。 完成上面的设置后,我们可以在每个Pass中使用标签来指定该Pass使用的渲染路径。 指定渲染路径是我们和Unity的底层渲染引擎的一次重要的沟通。 前向渲染路径 前向渲染路

    2024年04月27日
    浏览(35)
  • 第九章 排序

    1.插入类排序:是在一个已排好序的记录子集的基础上,每一步将下一个待排序的记录有序插入已排好序的记录子集,直到将所有待排记录全部插入为止 a.直接插入排序(稳定) b.折半插入排序(稳定) c.希尔排序(不稳定) 2.交换类排序:通过一系列交换逆序元素进行排序

    2024年02月02日
    浏览(33)
  • 第九章:Java常用类

    目录 9.1:字符串相关的类:String         9.1.1:String用法         9.1.2:String方法         9.1.3:String与char[]、byte[]之间的转换         9.1.4:StringBuffer和StringBuilder的使用 9.2:JDK 8之前的日期时间API 9.3:JDK 8中新日期时间API         9.3.1:LocalDate、LocalTime、LocalDateTime的使

    2024年02月09日
    浏览(41)
  • 第九章 番外篇:TORCHSCRIPT

    下文中的代码都使用参考教程中的例子。 会给出一点自己的解释。 参考教程: mixing-scripting-and-tracing script and optimize for mobile recipe https://pytorch.org/docs/stable/jit.html OPTIMIZING VISION TRANSFORMER MODEL FOR DEPLOYMEN 我们训练好并保存的pytorch,支持在python语言下的使用,但是不支持在一些

    2024年02月10日
    浏览(39)
  • 第九章 JUC并发编程

    http://t.csdn.cn/UgzQi 使用 AQS加 Lock 接口实现简单的不可重入锁 早期程序员会自己通过一种同步器去实现另一种相近的同步器,例如用可重入锁去实现信号量,或反之。这显然不够优雅,于是在 JSR166(java 规范提案)中创建了 AQS,提供了这种通用的同步器机制。 AQS 要实现的功能

    2023年04月08日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包