JavaScript ES(6-11)基础语法系列(5)

        

proxy代理

ES5代理:访问器属性

let obj = {}
let newVal = ''
Object.defineProperty(obj, 'age', {
  get() {
    console.log('get')
    return newVal
  },
  set(val) {
    console.log('set')
    console.log(val)
    newVal = val
  },
})
obj.age = 55
console.log(obj)

Es6 proxy代理

Proxy 对象用于创建一个对象(对象和数组)的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

语法

const p = new Proxy(target, handler)
//参数
//target
//要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
//handler   配置了代理所需要的钩子函数
//一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。

handler中常用的钩子函数

handler.get(target,prop) 方法用于拦截对象的读取属性操作。

                        | |

目标对象 要获取的属性

handler.set(target,prop,val) 方法是设置属性值操作的捕获器。set() 方法应当返回一个布尔值。

                        |           |         |

                目标对象     |    设置的属性值

                        要设置的属性

handler.has(target,prop) 方法是针对 in 操作符的代理方法。

                         |           |

               目标对象      属性

const handler1 = {
  has(target, key) {
    if (key[0] === '_') {
      return false;
    }
    return key in target;
  }
};
​
const monster1 = {
  _secret: 'easily scared',
  eyeCount: 4
};
​
const proxy1 = new Proxy(monster1, handler1);
console.log('eyeCount' in proxy1);
// expected output: true
​
console.log('_secret' in proxy1);
// expected output: false
​
console.log('_secret' in monster1);
// expected output: true

handler.ownKeys() 方法用于拦截 Object.getOwnPropertyNames 方法、Object.getOwnPropertySymbols 方法Reflect.ownKeys()方法、for in 方法

const monster1 = {
  _age: 111,
  [Symbol('secret')]: 'I am scared!',
  eyeCount: 4
};
​
const handler1 = {
  ownKeys(target) {
    return Reflect.ownKeys(target);
  }
};
​
const proxy1 = new Proxy(monster1, handler1);
​
for (const key of Object.keys(proxy1)) {
  console.log(key);
  // expected output: "_age"
  // expected output: "eyeCount"
}

handler.deleteProperty() 方法用于拦截对对象属性的 delete 操作。deleteProperty 必须返回一个 Boolean 类型的值,表示了该属性是否被成功删除。

handler.apply() 方法用于拦截函数的调用。

var p = new Proxy(target, {
  apply: function(target, thisArg, argumentsList) {
  }
});
参数
// 以下是传递给apply方法的参数,this上下文绑定在handler对象上.
​
// target
// 目标对象(函数)。
// thisArg
// 被调用时的上下文对象。
// argumentsList
// 被调用时的参数数组。
// 返回值
// apply方法可以返回任何值。

handler.construct()方法用于拦截new 操作符. 为了使new操作符在生成的Proxy对象上生效,用于初始化代理的目标对象自身必须具有[[Construct]]内部方法(即 new target 必须是有效的)。

var p = new Proxy(target, {
  construct: function(target, argumentsList, newTarget) {
  }
});
// 参数
// 下面的参数将会传递给construct方法,this绑定在handler上。
​
// target
// 目标对象。
// argumentsList
// constructor的参数列表。
// newTarget
// 最初被调用的构造函数,就上面的例子而言是p。
// 返回值
// construct 方法必须返回一个对象。

 

 proxy 总结

 

Reflect总结

 

  • 将Object属于语言内部的方法放到Reflect上

var obj = {
  a:1
}
Reflect.defineProperty(obj,"a",{
  writable:false,
  enumerable:false
})
obj.a = 2
for(let key in obj){
  console.log(key);
}
console.log(obj);
  • 修改某些Object方法的返回结果,让其变得更合理

  • 让Object操作变成函数行为

  • Reflect对象的方法和Proxy对象方法一一对应

// 旧的方法
var obj = {
  a: 1
}
try {
  Object.defineProperty(obj,"a",{
    writable:false,
    enumerable:false
  })
  obj.a = 2
  for(let key in obj){
    console.log(key);
  }
  console.log(obj);
} catch (error) {
  err
}
// 新方法
var obj = {
  a: 1
}
if (Reflect.defineProperty(obj, "a", {
  writable: false,
  enumerable: true
})
) {
  obj.a = 2
  for (let key in obj) {
    console.log(key)
  }
}
  • Reflect让Object操作变成函数行为

console.log('assign' in Object) // true
console.log(Reflect.has(Object,'assign')) // true
  • Reflect对象的方法和Proxy对象的方法是一一对应的

let getSum = function(...args){
  let sum = 0
  args.forEach(e=>sum += e)
  return sum
}
getSum = new Proxy(getSum,{
  apply(target,txc,args) {
    return Reflect.apply(target,target,args)*2
  }
})
console.log(getSum(1,2));
console.log(getSum.apply(null,[1,2]));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值