ES6学习笔记(二)Proxy和Reflect

121 阅读2分钟

Proxy

在ES6中新增了一个类Proxy,用于帮助我们创建代理(也就是说如果创建一个对象,那么我们可以先创建一个代理对象,也就是Proxy对象,之后对该对象的所有操作,都通过代理对象来完成)
const obj = {
  name: 'lhm',
  age: 18
}

const objProxy = new Proxy(obj, {
  // 获取值时的捕获器,target是指原对象,也就是obj;key是获取的key值;receiver是指代理对象
  get: function (target, key, receiver) {
    return target[key]
  },
  // 设置值时的捕获器,target,key和receiver如上,newValue是新的赋值
  set: function (target, key, newValue, receiver) {
    target[key] = newValue
  },
  // 监听in的捕获器
  has: function(target, key) {
    return key in target
  },
  // 监听delete捕获器
  deleteProperty: function(target, key) {
    delete target[key]
  }
})

console.log(objProxy.name); // lhm
console.log(objProxy.age);  // 18

// 更改代理对象时,原对象也会同步跟着更改
objProxy.name = 'kobe'
objProxy.age = 30

console.log(obj.name);  // kobe
console.log(obj.age);  // 30

Proxy一共有13种捕获器,除以上4种如下:
(1) handler.getPrototypeOf(): Object.getPrototypeOf方法的捕获器。(getPrototypeOf是获取对象的原型)
(2) handler.setPrototypeOf(): Object.setPrototypeOf方法的捕获器。(setPrototypeOf是设置对象的原型)
(3) handler.isExtensible(): Object.isExtensible方法的捕获器。(isExtensible是判断某一个对象是否能扩展)
(4) handler.preventExtensions(): Object.preventExtensions方法的捕获器。(preventExtensions方法将对象变得不可扩展)
(5) handler.getOwnPropertyDescriptor(): Object.getOwnPropertyDescriptor方法的捕获器。(getOwnPropertyDescriptor返回指定对象上一个自有属性对应的属性描述符)
(6) handler.definProperty(): Object.definProperty方法的捕获器。(definProperty是设置对象的属性描述符)
(7) handler.getOwnKeys(): Object.getOwnPeropertyNames方法和Object.getOwnPropertySymbols的捕获器。
(8) handler.apply(): 函数调用的捕获器。
(9) handler.construct(): new操作符的捕获器。

Reflect

Reflect是ES6新增的API,它是一个对象,字面的意思是反射,它主要提供了很多操作JavaScript对象的方法,有点像Object操作对象的方法,如果想查看Reflect和Object的区别,请点击 Reflect有13种常见方法,和Proxy的13种常见方法一一对应
const obj = {
  name: 'lhm',
  age: 18
}

const objProxy = new Proxy(obj, {
  get: function (target, key, receiver) {
    // 等同于target[key]
    return Reflect.get(target, key)
  },
  set: function (target, key, newValue, receiver) {
    // 等同于target[key] = newValue, 较比target[key] = newValue,result会返回一个设置成功或失败的布尔值,
    const result = Reflect.set(target, key, newValue)
  }
})

objProxy.name = 'kobe'
console.log(objProxy.name);  // kobe
关于received参数的作用
const obj = {
  _name: 'lhm',
  get name() {
    return this._name
  },
  set name(newValue) {
    this._name = newValue
  }
}

const objProxy = new Proxy(obj, {
  get: function(target, key, receiver) {
    console.log('被访问了');
    // receiver是代理对象,没有传receiver,target指的是obj的name属性,obj中的this指向obj,如果传了则obj的this指的是received,这个Proxy的get会执行两次,一次是name被访问,另一次是_name被访问
    return Reflect.get(target, key, receiver)
  },
  // 只有get和set有received,received作用如上
  set: function (target, key, newValue, receiver) {
    Reflect.set(target, key, newValue, receiver)
  }
})

objProxy.name = 'kobe'
console.log(objProxy.name);  // kobe