ECMAScript 6 笔记(16)- Proxy (2)

原创 乘风逐月 随笔 ES6 178阅读 2018-09-21 17:33:00 举报

一、Proxy 实例的方法

1.defineProperty()

defineProperty 方法拦截了 Object.defineProperty 操作。
该方法接受三个参数:目标对象、属性名、属性描述符。该方法返回 false,导致添加新属性总是无效。
(Object.defineProperty 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象)

注:如果目标对象的某个属性不可写或不可配置,则 defineProperty 方法不得改变这两个设置。如果目标对象不可扩展,defineProperty 方法不能增加目标对象上不存在的属性,否则会报错。

2.getOwnPropertyDescriptor()

getOwnPropertyDescriptor 方法拦截 Object.getOwnPropertyDescriptor(),返回一个属性描述对象或者 undefined。

上例中,handler 的 getOwnPropertyDescriptor 方法对第一个字符为下划线的属性名返回 undefined。

3.getPrototypeOf()

getPrototypeOf 方法主要用来拦截获取对象原型。具体拦截以下操作:
a. prototypeObj.isPrototypeOf(object): 检查一个对象是否存在于另一个对象的原型链上。
b. Object.getPrototypeOf(obj): 获取参数对象的原型对象
c. instanceOf:测试构造函数的原型是否出现在对象的原型链中。

注意:
a. getPrototypeOf 方法的返回值必须是对象或者 null,否则会报错。
b. 如果目标对象不可扩展,getPrototypeOf 方法必须返回目标对象的原型对象。

4.isExtensible()

isExtensible 方法拦截 Object.isExtensible 操作。
(Object.isExtensible() 方法判断一个对象是否是密封对象,返回布尔值)

注意:
a. isExtensible 方法只能返回布尔值,如果返回值不是布尔值会被自动转为布尔值。
b. isExtensible() 方法有一个强限制,返回值必须与目标对象的 isExtensible 返回值一致,否则报错。

5.ownKeys()

ownKeys() 方法用来拦截对象自身属性的读取操作。,具体拦截以下操作:
a. Object.getOwnPropertyNames(obj):返回一个数组,包含对象自身的所有可枚举属性名(不包含 Symbol 属性)。
b. Object.getOwnPropertySymbols(obj):返回一个数组,包含对象的所有 Symbol 属性名。
c. Object.keys(): 返回一个数组,包含对象自身的所有可枚举属性名,不包含 symbol 属性。
d. for...in: 返回对象自身和继承的所有可枚举属性,不包含 symbol 属性。

注意:
a. ownKeys() 方法返回的数组成员,只能是字符串或者 Symbol 值。如果有其他类型的值,或者返回的不是数组,都会报错。
b. 如果目标对象自身包含不可配置的属性,则该属性必须被返回,否则报错。
c. 如果目标对象是不可扩展的,则 ownKeys 方法返回的数组之中,必须包含原对象的所有属性,且不能包含多余的属性,否则会报错。

6.preventExtensible()

preventExtensible 方法拦截 Object.preventExtensions()。该方法必须返回一个布尔值,否则会自动转为布尔值。
(Object.preventExtensions():使一个对象变得不可扩展,不能添加新属性。)

7.setPrototypeOf()

setPrototypeOf 方法主要用来拦截 Object.setPrototypeOf() 方法。
(Object.setPrototypeOf(obj,prototype) 方法用来指定一个对象的原型。)

注:如果目标对象不可扩展,setPrototypeOf 方法不得改变目标对象的原型。

二、Proxy.revocable()方法

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

上例中,Proxy.revocable 方法返回一个对象,该对象的 proxy 属性是 Proxy 实例。revoke 属性是一个函数,可以取消 Proxy 实例。

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

三、 this 问题

虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,既不做任何拦截的情况下,也无法与目标对象的行为一致。主要原因是在 Proxy 代理的情况下,目标对象内部的 this 关键字会指向 Proxy 代理。

上例中, proxy 代理 target.m ,内部的 this 就是指向 proxy,而不是 target。
注意:
有些原生对象的内部属性,只能通过正确的 this 才能拿到,所以 Proxy 无法代理这些原生对象的属性。

评论 ( 9 )
最新评论
lawrence 8F 2018-09-30 20:25:56 9F

平时不用加班么

乘风逐月 7F 2018-09-26 11:20:23 8F

是的

lawrence 6F 2018-09-25 19:32:24 7F

你准备把 高级程序设计看完么

乘风逐月 5F 2018-09-25 17:20:44 6F

JavaScript 高级程序设计,JavaScript 面向对象编程指南,ES6 入门

lawrence 4F 2018-09-25 15:27:44 5F

你是看哪本书学JS的?

乘风逐月 3F 2018-09-25 15:23:24 4F

工作中用不用是一回事,自己学不学又是另一回事。很多时候工作中都用不到那些,难道就都不用学吗?

lawrence 2F 2018-09-25 15:10:55 3F

那你学它是干啥?

乘风逐月 1F 2018-09-25 09:21:42 2F

我几乎没有用过。

lawrence 2018-09-24 16:33:42 1F

defineProperty这种接口平时是不是用的很少?