ES6 -- 最佳代理Proxy:实例方法
来源:互联网 发布:vscode mysql 编辑:程序博客网 时间:2024/06/06 00:06
get方法
该方法用来代理属性的读取操作。当用户希望访问对象的某个属性时,会直接触发这个方法,而不是默认的读取属性方法。
栗子:
var car = { brank: "Benz"};var proxy = new Proxy(car, { get: function(target, property) { if (property in target) { return target[property]; } else { throw new ReferenceError("Property \"" + property + "\" does not exist."); } }});proxy.brank // "Benz"proxy.year // Error:Property year does not exist.
本栗中,如果访问的属性存在,将会返回属性值,但是如果属性不存在,则会抛出错误。在平常的情况下,如果访问的属性不存在,只是会返回undefined,不会报错。
利用proxy,可以实现函数的链式调用:(代码来自阮一峰大神ES6博客)
var pipe = (function () { return function (value) { var funcStack = []; var oproxy = new Proxy({} , { get : function (pipeObject, fnName) { if (fnName === 'get') { return funcStack.reduce(function (val, fn) { return fn(val); },value); } funcStack.push(window[fnName]); return oproxy; } }); return oproxy; }}());var double = n => n * 2;var pow = n => n * n;var reverseInt = n => n.toString().split("").reverse().join("") | 0;pipe(3).double.pow.reverseInt.get; // 63
代码分析:如果想要实现函数的链式调用,就需要将可以调用某函数的对象作为函数的返回值。在上面这个栗子中,对oproxy的属性(方法其实也可以看做属性)的访问总会被代理函数get拦截,并根据我们部署的代码,在函数的最后返回oproxy对象。这样,对于这个对象的方法的访问,就可以链式不断的调用下去,因为每个方法调用后,都会返回原对象。
限制:如果对象的属性被设置为configurable:false或者writable:false,那么这时候,get属性将不能被代理,通过Proxy访问该属性会报错。
const cantChangeObj = Object.defineProperties({}, { foo: { value: 123, writable: false, configurable: false },});const handler = { get(target, propKey) { return 'geting'+propKey+'from'+target; }};const proxy = new Proxy(cantChangeObj, handler);proxy.foo// TypeError: Invariant check failed
set方法
set方法用来代理对象某个属性的赋值操作。通过set,我们就可以获得对属性值的类型、大小等等的掌控能力。
let validate = { set: function(obj, prop, value) { if (prop === 'year') { if (!Number.isInteger(value)) { throw new TypeError('The year must be an integer'); } if (year < 2000) { throw new RangeError('The year seems invalid'); } } // 对于year以外的属性,可以直接保存,或使用if增加其他判断 obj[prop] = value; }};let car = new Proxy({}, validate);car.year = 2001;car.year // 2001car.year = 'Benz' // 报错car.year = 1999 // 报错
上述代码对car对象的year属性设置了范围:首先必须是数字,其次,必需要在2000以后(太老旧的车不能通过验证)。
应用1: 对于set方法我们还可以将数据与DOM元素绑定,每当元素值发生变化,DOM也就相应的发生变化。
应用2: 有些对象的内部属性,是我们不希望他人有意或无意修改的,通常会用下划线“_”开头,set方法可以帮助我们切实的阻止他人对此类对象的访问。
var handler = { get (target, key) { invariant(key, 'get'); return target[key]; }, set (target, key, value) { invariant(key, 'set'); target[key] = value; return true; }};function invariant (key, action) { if (key[0] === '_') { throw new Error(`Invalid attempt to ${action} private "${key}" property`); }}var target = {};var proxy = new Proxy(target, handler);proxy._prop// Error: Invalid attempt to get private "_prop" propertyproxy._prop = 'c'// Error: Invalid attempt to set private "_prop" property
限制:同get一样,如果目标对象自身的某个属性,不可写也不可配置,那么set不得改变这个属性的值,只能返回同样的值,否则报错。
apply方法
apply可以代理call和apply两个操作(因为这两个操作本质上做的事情都一样嘛)。
apply方法的三个参数:目标对象、目标对象的上下文对象(this)和目标对象的参数数组。
一个最简单的栗子:
var target = function () { return 'I am the target'; };var handler = { apply: function () { return 'I am the proxy'; }};var p = new Proxy(target, handler);p()// "I am the proxy"
当p被作为函数调用的时候(p()),代理方法apply就会生效,返回的是apply函数的字符串。
另一个稍微复杂的栗子:
var twice = { apply (target, ctx, args) { return Reflect.apply(...arguments) * 2; }};function sum (left, right) { return left + right;};var proxy = new Proxy(sum, twice);proxy(1, 2) // 6proxy.call(null, 5, 6) // 22proxy.apply(null, [7, 8]) // 30
总上面几个代码我们可以总结出——apply代理的途径包括:1、当直接执行proxy函数时,2、proxy调用call或者apply时。
has方法
has方法将作为方法HasProperty的代理,HasProperty的功能是判断对象是否具有某个属性。
应用1: 使用has方法,可以帮助我们隐藏某些属性,不被in运算符发现。
var handler = { has (target, key) { if (key === 'privateProp') { return false; } return key in target; }};var target = { privateProp: 'myPassword', prop: 'foo' };var proxy = new Proxy(target, handler);'privateProp' in proxy // false
需要注意的是,has方法代理的方法是HasProperty(在没有任何其他配置的前提下,一个对象自身的属性和继承的属性都可以被此方法找到),而不是HasOwnProperty(此方法尽可以找到属于对象自身的属性)。还需要注意,has只对in运算符有效,而不是for…in…。
限制:如果原对象被设置为不可配置/禁止扩展,那么,该操作就会报错:
var obj = { a: 10 };Object.preventExtensions(obj);var p = new Proxy(obj, { has: function(target, prop) { return false; }});'a' in p // TypeError is thrown
- ES6 -- 最佳代理Proxy:实例方法
- ES6 -- 最佳代理:Proxy
- es6 javascript的Proxy 实例的方法
- 十二,ES6 新增Proxy代理
- 深度揭秘ES6代理Proxy
- Javascript/ES6代理Proxy用法
- 初步探究ES6之Proxy代理
- 初步探究ES6之Proxy代理
- ES6 proxy
- 【ES6】Proxy
- ES6 Proxy
- es6-Proxy
- es6-Proxy
- ES6-proxy
- es6 Proxy
- 【ES6】Proxy
- ES6学习之路(六) Proxy 代理器&Reflect
- ES6——Proxy(代理)、Reflect(反射)
- Bow模型
- UML简介---三大模型和五大类图
- Android的四种线程池及各自特点
- SQL Server连接多数据库
- linux中文件查找:find
- ES6 -- 最佳代理Proxy:实例方法
- Spring 之spring helloworld
- C++Primer第5版读书笔记(第14章)
- AR追风-2017企业网络推广及新媒体经验分享!
- Python3 操作系统与路径 模块(os / os.path / pathlib)
- mybatis的主配置文件的配置
- C语言趣味程序(1)
- 程序设计模式(二) C++抽象工厂(Abstract Factory)模式
- 欢迎使用CSDN-markdown编辑器