proxy学习笔记整理

proxy(代理)亦可理解为发言代表

syntax: const proxy = new Proxy(target, handle)
释义:proxy是生成的发言代表,target是需要被代表发言的对象handle是发言代表需要遵守的规则,也是一个对象

先抛一个小例子,热热身:

const obj = {a:1}
const handle = {
  get: function(target, propKey){
	return '我就不告诉你!'
  }
}
const proxy = new Proxy(obj, handle)
proxy.a		// "我就不告诉你!"
obj.a 		// 1

看,proxy(代理)可坏了,它得知并拦截了你访问obj的操作(get),还不好好回答你问题!当你见不到obj本人时,你从proxy那获取到的obj信息,其实是proxy的handle胡诌的答案,并不一定真实、有效!

参考阮一峰的《ES6入门》,代理能够拦截的操作有以下13种:

1. get(target, propKey, receiver)

拦截的操作:对象属性的读取,比如proxy.foo和proxy[‘foo’];
参数释义
target——目标对象
propKey——属性名
receiver——【可选】操作行为所针对的对象。①如果是你通过代理访问target的属性,那么receiver就指向代理;②如果你是以代理为原型新生成了一个对象,则receiver指向该对象。
返回值:想return啥return啥~

示例,这里阮一峰举了三个很好的例子(其实例子有好几个,但是复杂点的就3个),我就不献丑了~

*: 如果一个属性不可配置(configurable)且不可写(writable),则 Proxy 不能修改该属性的get操作,否则通过 Proxy 对象访问该属性会报错。

2. set(target, propKey, value, receiver)

拦截的操作:对象属性的设置,比如proxy.foo = v或proxy[‘foo’] = v;
参数释义
target——目标对象
propKey——属性名
value——属性值
receiver——【可选】操作行为所针对的对象。
返回值:布尔值。

*:①如果目标对象自身的某个属性,不可写且不可配置,那么set方法将不起作用;②严格模式下,set代理如果没有返回true,就会报错

3. has(target, propKey)

拦截的操作:propKey in proxy的操作;
参数释义
target——目标对象
propKey——需查询的属性名
返回值:布尔值。

*:
①如果原对象不可配置或者禁止扩展,这时has拦截会报错;
②has方法拦截的是HasProperty操作,而不是HasOwnProperty操作,即has方法不判断一个属性是对象自身的属性,还是继承的属性;
③has拦截对for…in循环不生效;
proxy学习笔记整理_第1张图片

4. deleteProperty(target, propKey)

拦截的操作delete proxy[propKey]的操作;
参数释义
target——目标对象
propKey——目标对象的属性名
返回值:布尔值。

*:
①如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除;
②目标对象自身的不可配置(configurable)的属性,不能被deleteProperty方法删除,否则报错。

5. ownKeys(target)

拦截的操作:对象自身属性的读取操作。如:
Object.getOwnPropertyNames(proxy)
Object.getOwnPropertySymbols(proxy)
Object.keys(proxy)
for...in循环
返回值:一个数组(数组成员,只能是字符串或 Symbol 值)。该方法返回目标对象所有自身的属性的属性名,而Object.keys(proxy)的返回结果仅包括目标对象自身的可遍历属性。

看这个例子:
p和target都不包含a,b,c三个属性,但三种拦截方式的返回值都不同(Object.getOwnPropertyNames(proxy)是return啥,它就返回啥;for…inObject.keys(proxy)则是在return里面找本身确实有的属性返回)
proxy学习笔记整理_第2张图片

*:
①使用Object.keys()方法时,有三类属性会被ownKeys()方法自动过滤,不会返回。

  • 目标对象上不存在的属性
  • 属性名为 Symbol 值
  • 不可遍历(enumerable)的属性

②如果目标对象自身包含不可配置的属性,则该属性必须被ownKeys()方法返回,否则报错;
③如果目标对象是不可扩展的(non-extensible),这时ownKeys()方法返回的数组之中,必须包含原对象的所有属性,且不能包含多余的属性,否则报错。

6. getOwnPropertyDescriptor(target, propKey)

拦截的操作Object.getOwnPropertyDescriptor(proxy, propKey)
返回值:proxy的propKey属性的描述对象。

7. defineProperty(target, propKey, propDesc)

拦截的操作
Object.defineProperty(proxy, propKey, propDesc)
Object.defineProperties(proxy, propDescs)
参数释义
target——目标对象
propKey——目标对象的属性名
propDesc——目标对象属性的描述器
返回值:布尔值。

*:
①如果目标对象不可扩展(non-extensible),则defineProperty()不能增加目标对象上不存在的属性,否则会报错;
②如果目标对象的某个属性不可写(writable)或不可配置(configurable),则defineProperty()方法不得改变这两个设置。

8. preventExtensions(target)

拦截的操作Object.preventExtensions(proxy)
返回值:必须返回一个布尔值,否则会被自动转为布尔值。

注*:该方法有一个限制,只有目标对象不可扩展时(即Object.isExtensible(proxy)为false),proxy.preventExtensions才能返回true,否则会报错。

9. getPrototypeOf(target)

拦截的操作
Object.prototype.__proto__
Object.prototype.isPrototypeOf()
Object.getPrototypeOf()
Reflect.getPrototypeOf()
instanceof
返回值:一个对象或者null。

*:如果目标对象不可扩展(non-extensible), getPrototypeOf()方法必须返回目标对象的原型对象。

10. isExtensible(target)

拦截的操作Object.isExtensible(proxy)
返回值:只能返回布尔值,否则返回值会被自动转为布尔值。

*:该方法有一个强限制:返回值必须与目标对象的isExtensible属性保持一致,否则就会抛出错误(即不能谎报军情)。

11. setPrototypeOf(target, proto)

拦截的操作Object.setPrototypeOf(proxy, proto)
返回值:布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截(见12、13)。

*:如果目标对象不可扩展(non-extensible),setPrototypeOf()方法不得改变目标对象的原型。

12. apply(target, object, args)

拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)proxy.call(object, ...args)proxy.apply(...)

参数释义
target——目标对象
object——目标对象的上下文对象(this)
args——目标对象的参数数组

13. construct(target, args, newTarget)

拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(…args)。
参数释义
target:目标对象
args:构造函数的参数对象
newTarget:new命令作用的构造函数
返回值:必须是一个对象,否则会报错。


从这开始,不是proxy拦截的操作了!

Proxy.revocable()

Proxy.revocable()方法返回一个可取消的 Proxy 实例。

let target = {};
let handler = {};

let {proxy, revoke} = Proxy.revocable(target, handler);

proxy.foo = 123;
proxy.foo // 123

revoke();
proxy.foo // TypeError: Revoked

使用场景:目标对象不允许直接访问,必须通过代理访问,一旦访问结束,就收回代理权,不允许再次访问。

还有以下this指向问题,导致的proxy和target表现不一致的问题,以及proxy在对象拦截方面的潜力,请自行看阮一峰的书或是查资料(Vue3.0数据响应)~

此致

你可能感兴趣的:(前端学习,proxy,JavaScript,ES6)