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

原创 乘风逐月 随笔 ES6 127阅读 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 23 天前 9F

平时不用加班么

是的

lawrence 6F 28 天前 7F

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

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

lawrence 4F 28 天前 5F

你是看哪本书学JS的?

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

lawrence 2F 28 天前 3F

那你学它是干啥?

我几乎没有用过。

lawrence 29 天前 1F

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