# 前言声明
# 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) |