# 前言声明
# Proxy
# handler.get()
| const lain = { |
| name: 'lain', |
| age: 16 |
| } |
| |
| const lainProxy = new Proxy(lain, { |
| |
| get(target, property) { |
| console.log(`lainProxy 的 ${property} 属性被访问了`, target) |
| return target[property] |
| } |
| }) |
| |
| |
| console.log(lainProxy.name) |
# handler.set()
**handler.set()**
方法是设置属性值操作的捕获器。
target
目标对象
property
将被设置的属性名或 Symbol
。
value
新属性值
receiver
最初被调用的对象。通常是 proxy 本身,但 handler 的 set 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。
| const lain = { |
| name: 'lain', |
| age: 16 |
| } |
| |
| const lainProxy = new Proxy(lain, { |
| |
| set(target, property, newValue) { |
| console.log(`lainProxy 的 ${property} 属性被设置为 ${newValue}`, target) |
| target[property] = newValue |
| } |
| }) |
| |
| |
| lainProxy.name = 'saber' |
# handler.has()
-
handler.has()
方法是针对 in
操作符的代理方法。
target
目标对象
prop
需要检查是否存在的属性.
has
方法返回一个 boolean 属性的值.
**handler.has**
方法可以看作是针对 in
操作的钩子.
| const lain = { |
| name: 'lain', |
| age: 16 |
| } |
| |
| const lainProxy = new Proxy(lain, { |
| has(target, prop) { |
| return prop in target |
| } |
| }) |
| |
| console.log('name' in lainProxy) |
| console.log('friends' in lainProxy) |
# handler.defineProperty()
-
handler.defineProperty()
用于拦截对对象的 Object.defineProperty()
操作。
target
目标对象
property
待检索其描述的属性名
descriptor
待定义或修改的属性的描述符
defineProperty
方法必须以一个 Boolean
返回,表示定义该属性的操作成功与否。
| const lain = { |
| name: 'lain', |
| age: 16 |
| } |
| |
| const lainProxy = new Proxy(lain, { |
| deleteProperty(target, prop) { |
| console.log(target, prop) |
| delete target[prop] |
| } |
| }) |
| |
| delete lainProxy.age |
| |
| console.log(lainProxy) |
# handler.deleteProperty()
-
handler.getPrototypeOf()
是一个代理(Proxy)方法,当读取代理对象的原型时,该方法就会被调用。
target
被代理的目标对象。
handler
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p
的行为。
getPrototypeOf
方法的返回值必须是一个对象或者 null
。
| const lain = { |
| name: 'lain', |
| age: 16 |
| } |
| |
| const foo = {} |
| |
| const handel = { |
| getPrototypeOf(target) { |
| return lainProxy |
| } |
| } |
| |
| const lainProxy = new Proxy(lain, handel) |
| |
| console.log(Object.getPrototypeOf(lainProxy) === lain) |
| |
| console.log(Object.getPrototypeOf(lainProxy) === foo) |
| |
| console.log(Object.getPrototypeOf(lainProxy) === lainProxy) |
# handler.apply()
-
handler.apply()
方法用于拦截函数的调用。
target
被代理的目标对象。
thisArg
被调用时的上下文对象
apply
方法可以返回任何值。
| const lain = { |
| name: 'lain', |
| age: 16 |
| } |
| |
| function foo() { |
| |
| } |
| |
| const handler = { |
| apply(target, thisArg, argArray) { |
| console.log(target, thisArg, argArray) |
| target.apply(thisArg, argArray) |
| } |
| } |
| |
| const fooProxy = new Proxy(foo, handler) |
| |
| fooProxy.apply(lain, ['我', '是', '参', '数']) |
# handler.construct()
-
handler.construct()
方法用于拦截 new
操作符。
target
被代理的目标对象。
argumentsList
constructor 的参数列表。
newTarget
最初被调用的构造函数,就上面的例子而言是 p。
construct
方法必须返回一个对象。
| function foo() { |
| |
| } |
| |
| const handler = { |
| construct(target, argArray, newTarget) { |
| console.log(target, argArray, newTarget) |
| console.log(newTarget === fooProxy) |
| return new target(...argArray) |
| } |
| } |
| |
| const fooProxy = new Proxy(foo, handler) |
| |
| new fooProxy('我', '是', '参', '数') |
# Reflect
# Reflect.get()
-
**Reflect**
** .get()
** 方法与从 对象 ( target[propertyKey]
) 中读取属性类似,但它是通过一个函数执行来操
-
target
需要取值的目标对象
-
propertyKey
需要获取的值的键值
-
receiver
如果 target
对象中指定了 getter
, receiver
则为 getter
调用时的 this
值。
-
返回值
属性的值。
-
Reflect.get
方法允许你从一个对象中取属性值。就如同属性访问器 语法,但却是通过函数调用来实现。
| const lain = { |
| name: 'lain', |
| age: 16 |
| } |
| |
| const lainProxy = new Proxy(lain, { |
| get(target, key, receiver) { |
| console.log('Reflect get') |
| |
| const returnValue = Reflect.get(target, key, receiver) |
| |
| console.log(returnValue) |
| } |
| }) |
| |
| lainProxy.name |
# Reflect.set()
- 静态方法
**Reflect**
.set()
工作方式就像在一个对象上设置一个属性。
语法
Reflect.set(target, propertyKey, value[, receiver])
- ·
propertyKey
设置的属性的名称。
value
设置的值。
receiver
如果遇到 setter
, receiver
则为 setter
调用时的 this
值。
- 返回一个
Boolean
值表明是否成功设置属性。
| const lain = { |
| name: 'lain', |
| age: 16 |
| } |
| |
| const lainProxy = new Proxy(lain, { |
| set(target, key, newValue, receiver) { |
| console.log('Reflect set') |
| |
| const res = Reflect.set(target, key, newValue, receiver) |
| |
| console.log(res) |
| } |
| |
| }) |
| |
| lainProxy.name = 'saber' |
# receiver 参数作用
| const lain = { |
| _name: 'lain', |
| get name() { |
| |
| console.log(this === lain) |
| console.log(this === lainProxy) |
| return this._name |
| } |
| } |
| |
| const lainProxy = new Proxy(lain, { |
| get(target, key, receiver) { |
| |
| console.log('key:', key) |
| |
| return Reflect.get(target, key) |
| } |
| }) |
| |
| |
| lainProxy.name |
| const lain = { |
| _name: 'lain', |
| get name() { |
| |
| console.log(this === lain) |
| console.log(this === lainProxy) |
| |
| return this._name |
| } |
| } |
| |
| const lainProxy = new Proxy(lain, { |
| get(target, key, receiver) { |
| |
| console.log('key:', key) |
| |
| return Reflect.get(target, key, receiver) |
| } |
| }) |
| |
| |
| lainProxy.name |
- 那么
set
传入了 receiver
效果也是一样~
| const lain = { |
| _name: 'lain', |
| get name() { |
| return this._name |
| }, |
| set name(newValue) { |
| |
| console.log(this === lainProxy) |
| |
| this._name = newValue |
| } |
| } |
| |
| const lainProxy = new Proxy(lain, { |
| set(target, key, newValue, receiver) { |
| |
| console.log('set:', key) |
| |
| Reflect.set(target, key, newValue, receiver) |
| } |
| }) |
| |
| lainProxy.name = 'saber' |
# Reflect.construct()
**Reflect**
.construct()
方法的行为有点像 new
操作符 构造函数 , 相当于运行 new target(...args)
**语法 Reflect.construct(target, argumentsList[, newTarget])**
target
被运行的目标构造函数
argumentsList
类数组,目标构造函数调用时的参数。
- ``newTarget 可选
作为新创建对象的原型对象的 constructor
属性, 参考 new.target
操作符,默认值为 target。
- 以
target
(如果 newTarget
存在,则为 newTarget
)函数为构造函数, argumentList
为其初始化参数的对象实例。
| function Foo(name, age) { |
| this.name = name |
| this.age = age |
| } |
| |
| function Bar() { |
| |
| } |
| |
| const foo = new Foo() |
| |
| |
| |
| const bar = Reflect.construct(Foo, ['Lain', 16], Bar) |
| |
| console.log(bar) |
| |
| console.log(bar.__proto__ == Bar.prototype) |