在实际开发中经常会遇到js抛出的错误,但是我们有没有想过自己去接管js异常验证,根据自己的需求抛出异常呢?原本也许不行,但是在es6出来后就可以做到了

一、代理(Proxy)

什么是‘代理’ 呢?代理:就是调用new 创建一个和目标(traget)对象一直的虚拟化对象,然该代理中就可以拦截JavaScript引擎内部目标的底层对象的操作;这些底层操作被拦截后会触发响应特定操作的陷阱函数

来看个简单的案例

    let tartget = {};
let proxy = new Proxy(target,{});
proxy.name = 'proxy';
console.log(proxy.name); // proxy
console.log(tartget .name); // proxy tartget .name = 'tartget';
console.log(proxy.name); // target
console.log(tartget .name); // target

如案例

proxy.name = 'proxy'; 将proxy赋值给proxy.name时,代理就会将该操作转发给目标,执行name属性的创建;然而他只是做转发而不会存储该属性;

so他们之间存在一个相互引用;tartget .name设置一个新值后,proxy.name值也改变了;

二、反射(Reflect)

那反射又是什么呢?反射:它提供了一个Reflect对象API;该对像中的方法默认特性与底层的操作对应;而每一个代理陷阱会对应一个命名和参数都相同的Reflect方法(其实就是每个代理陷阱都会对应一个Reflect api接口供覆写JavaScript底层操作)

映射关系如下表:

代理陷阱 覆写的特性 默认特性
get 读写一个属性值 Reflect.get()
set 写入一个属性 Reflect.set()
has in操作 Reflect.has()
deleteProperty delete操作符 Reflect.deleteProperty()
getAPrototypeof Object.getAPrototypeof () Reflect.getAPrototypeof ()
setAPrototypeof Object.setAPrototypeof () Reflect.setAPrototypeof ()
isExtensible Object.isExtensible() Reflect.isExtensible()
preventExtensions Object.preventExtensions() Reflect.preventExtensions()
getOwnPropertyDescriptor Object.getOwnPropertyDescriptor() Reflect.getOwnPropertyDescriptor()
defineaProperty Object.defineaProperty() Reflect.defineaProperty()
ownKeys Object.keys() 、 Object.getOwnPropertyNames()和 Object.getOwnPropertySysmbols() Reflect.ownKeys()
apply 调用一个函数 Reflect.apply()
construct 用new调用一个函数 Reflect.construct()

三、使用set陷阱验证属性

接下来使用set陷阱来验证一下对象属性赋值操作(如为对象新增属性,要求必须赋值为int)

let target = {
name :'target'
};
let proxy = new Proxy(target,{
set(trapTarget,key,value,receiver){
//忽略不希望受到影响的已有属性
if(!trapTarget.hasOwnProperty(key)){
if(isNaN(value)){
throw new TypeError("属性必须是数字哟,亲!");
}
}
// 添加属性
return Reflect.set(trapTarget,key,value,receiver);
}
}); // 添加一个新属性
proxy.count = 1;
console.log(proxy.count); // 1
console.log(proxy.count); // 1 // 由于目标已有name属性,so 如上第一个if不成立(赋值成功)
proxy.name= "proxy";
console.log(proxy.name); // proxy
console.log(proxy.name); // proxy // 新建一个属性同时赋值一个非int 值,第一个if成立,第二个if验证isNaN(key) = true 即抛出异常
proxy.anotherName = "proxy";

案例中set(trapTarget,key,value,receiver) 这个set陷阱默认接收 四个参数

  • trapTarget 用于接收属性(代理的目标)的对象
  • key 要写入的属性键(字符串或Symbol类型)
  • value 被写入的属性的值
  • receiver 操作发生的对象(通常是代理)

四、使用get 陷阱验证对象结构

let target = {};
console.log(target.name); // undefined

在JavaScript中调用一个对象不存在的属性不会报错,反而使用undefined代替被读取属性的值

而喝多时候会带来意想不到的bug,现在我们可以使用get陷阱来验证该问题

依然看这个案例

    let proxy = new Proxy(target,{
get(trapTarget,key,receiver){
//忽略不希望受到影响的已有属性
if(!(key in receiver)){
throw new TypeError("sorry 亲! 你找的 "+key+" 属性不存在。!")
}
// 添加属性
return Reflect.get(trapTarget,key,receiver);
}
});
// 添加一个属性,
proxy.name= "proxy";
console.log(proxy.name); // proxy // 读取一个不存在的属性 直接会抛出异常
console.log(proxy.nme);

如上使用in操作判断receiver中是否存在被读取的属性;如果没有抛出异常

其中get(trapTarget,key,receiver) 参数

  • trapTarget 被读取属性源对象(代理的目标)
  • key 要读取的属性键(字符串或Symbol类型)
  • receiver 操作发生的对象(通常是代理)

五、函数代理apply和construct陷阱

使用这个两个陷阱来验证函数调用时的参数的正确性

如下案例

// 参数求和
function sum (...values){
return values.reduce((previous,current) => prvious + current, 0);
} let sumProxy = new Proxy(sum,{
apply:function(trapTarget,thisArg,argumentList){
argumentList.forEach(arg => {
if(typeof arg !== "number"){
throw new TypeError("所有参数必须是数字,亲!");
}
});
return Reflect.apply(trapTarget,thisArg,argumentList);
},
// 防止使用new 关键字调用
construct:function(trapTarget,argumentList){
throw new TypeError("亲,你不能这么干,该函数不能通过new调用。");
}
}); // 测试哈
console.log(sumProxy(1,2,3,4)); // 10 // 传入一个非数字的属性值试试 【直接抛出异常】
console.log(sumProxy(1,“2”,3,4)); // 10 // 同样使用new调用 【直接抛出异常】
let result = new sumProxy();

apply陷阱和Reflect.apply()都接受同样的参数

  • trapTarget 被执行的函数(代理的目标)
  • thisArg 函数被调用时内部的this的值
  • argumentList传递给函数的参数数组

当使用new调用函数时 会触发construct陷阱,接收的参数为

  • trapTarget 被执行的函数(代理的目标)
  • argumentList传递给函数的参数数组

其中Reflect.construct()第三个参数是newTarget 这是一个可选参数。用于指定该函数内部

new.target的值

看到这里有没有感觉这个对于js项目代码检测还是蛮有用处的呢。



ok先到这里,时间不早了改且休息了;改天继续…

js代理(Proxy) 和 反射(Reflection)的更多相关文章

  1. 代理(Proxy)和反射(Reflection)

    前面的话 ES5和ES6致力于为开发者提供JS已有却不可调用的功能.例如在ES5出现以前,JS环境中的对象包含许多不可枚举和不可写的属性,但开发者不能定义自己的不可枚举或不可写属性,于是ES5引入了O ...

  2. JAVA设计模式-动态代理(Proxy)源码分析

    在文章:JAVA设计模式-动态代理(Proxy)示例及说明中,为动态代理设计模式举了一个小小的例子,那么这篇文章就来分析一下源码的实现. 一,Proxy.newProxyInstance方法 @Cal ...

  3. [整理]C#反射(Reflection)详解

    本人理解: 装配件:Assembly(程序集) 晚绑定:后期绑定 MSDN:反射(C# 编程指南) -----------------原文如下-------- 1. 什么是反射2. 命名空间与装配件的 ...

  4. 【设计模式】学习笔记17:代理模式之保护代理与Java反射

    本文出自   http://blog.csdn.net/shuangde800 本笔记内容: 1. Java动态代理,反射机制 2. 保护代理 3. 应用保护代理实现的约会系统 ----------- ...

  5. Webpack代理proxy配置,解决本地跨域调试问题,同时允许绑定host域名调试

    Webpack代理proxy配置,解决本地跨域调试问题,同时允许绑定host域名调试 会撸码的小马 关注 2018.05.29 17:30* 字数 212 阅读 1488评论 0喜欢 2 接到上一章, ...

  6. 浅谈Java代理一:JDK动态代理-Proxy.newProxyInstance

    浅谈Java代理一:JDK动态代理-Proxy.newProxyInstance java.lang.reflect.Proxy:该类用于动态生成代理类,只需传入目标接口.目标接口的类加载器以及Inv ...

  7. AGS API for JS代理页的使用

    AGS API for JS代理页的使用 1.概述 代理页即使用后端语言编写的请求转发页面,部署在Web应用端.客户端请求先发送到该代理页,代理页再将该请求转发到服务器处理,服务器处理结果再经代理页转 ...

  8. C#反射(Reflection)详解

    1. 什么是反射2. 命名空间与装配件的关系3. 运行期得到类型信息有什么用4. 如何使用反射获取类型5. 如何根据类型来动态创建对象6. 如何获取方法以及动态调用方法7. 动态创建委托 1.什么是反 ...

  9. JAVA设计模式-动态代理(Proxy)示例及说明

    在Mybatis源码解析,一步一步从浅入深(五):mapper节点的解析文章的最后部分,我们提到了动态代理的概念,下面我们就简单了解一下动态代理. 一,概念 代理设计模式的目的就是在不直接操作对象的前 ...

  10. ArcGIS JS 使用Proxy之 Printing Tools unable to connect to mapServer

    ArcGIS JS使用Proxy.ashx将地图服务隐藏,并在微博服务器端增加了地图服务权限判断. Proxy.ashx做了如下设置, <serverUrl url="http://l ...

随机推荐

  1. Linux & 标准C语言学习 <DAY6>

    一.数组     什么是数组:变量的组合,是一种批量定义相同类型变量的方式     定义:  类型名 数组名[数量];             int arr[5];             注意:数 ...

  2. 最大流应用(Maximum Flow Application)

    1. 二分图匹配(Bipartite Matching) 1.1 匹配(Matching) Def. Given an undirected graph \(G = (V, E)\), subset ...

  3. 记一次 .NET 某医疗住院系统 崩溃分析

    一:背景 1. 讲故事 最近收到了两起程序崩溃的dump,查了下都是经典的 double free 造成的,蛮有意思,这里就抽一篇出来分享一下经验供后面的学习者避坑吧. 二:WinDbg 分析 1. ...

  4. 这可能是最全面的Spring面试题总结了

    Spring是什么? Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架. Spring的优点 通过控制反转和依赖注入实现松耦合. 支持面向切面的编程,并且把应用业务逻辑和系统 ...

  5. Flutter中如何取消任务

    前言 在开发过程中,取消需求是很常见的,但很容易被忽略.然而,取消需求的好处也很大.例如,在页面中会发送很多请求.如果页面被切走并处于不可见状态,就需要取消未完成的请求任务.如果未及时取消,则可能会导 ...

  6. Android Banner - ViewPager 02

    Android Banner - ViewPager 02 现在来给viewpager实现的banenr加上自动轮播 自动轮播的原理,使用handler的延迟消息来实现. 自动轮播实现如下内容 开始轮 ...

  7. HOOPS Exchange助力Shapr3D产品实现了“无障碍的用户体验”

    HOOPS SDK是用于3D工业软件开发的工具包,其中包括4款工具,分别是用于 读取和写入30多种CAD文件格式的HOOPS Exchange.专注于Web端工程图形渲染的HOOPS Communic ...

  8. openGauss Datakit安装部署

    一.问题描述:目前找不到任何关于opengauuss Datakit安装部署的文档,自己来尝试踩坑. DataKit是一个以资源(物理机,数据库)为底座的开发运维工具,将上层的开发运维工具插件化,各插 ...

  9. sql计算众数及中位数

    众数 众数: 情况①:一组数据中,出现次数最多的数就叫这组数据的众数. 举例:1,2,3,3,4的众数是3. 情况② :如果有两个或两个以上个数出现次数都是最多的,那么这几个数都是这组数据的众数. 举 ...

  10. VUE3企业级项目基础框架搭建流程(2)

    typescript安装 这里使用的vue项目语言为:TypeScript,不了解的可以先去学习一下.TypeScript中文网 正常情况下安装typescript的命令为: // 全局安装 npm ...