最近公司在组织前端团队学习JavaScript高级程序设计(第四版)。这两天把第九章看完了,以下是精简版的学习笔记:

本章要点:

  1. proxy是代理的意思, 能够通过 构造函数 Proxy,给指标对象targetObj创立一个代理对象
  2. 对代理对象执行操作,会走handler里的办法,对源对象执行操作,不会
  3. 代理能够捕捉13中不同的根底api,handler中可定义多个捕捉办法
  4. 是一个全局的Reflect对象,所有捕捉的办法都有对应的Reflect api办法。它与捕捉器拦挡的办法同名、行为雷同。
  5. Reflect api 不限于捕捉处理程序handler,也可用在解决一般对象上
  6. 大多数Reflect api在Object上有对应的办法
  7. 有了Reflect后,能够不便写捕捉器
  8. 代理模式的几种利用

proxy

what?(Proxy是什么?)

proxy是代理的意思, 能够通过 构造函数 Proxy,给指标对象targetObj创立一个代理对象。

const proxyObj = new Proxy(targetObj, handlerObj) 

能够给对象obj创立一个代理。

why?(为什么用Proxy?)

当对代理对象进行一些对象操作时,会先执行代理中handlerObj对象定义的办法。

比方:

get( ) // 取对象属性set( ) // 往对象中增加属性 

how?(怎么用Proxy?)

对代理对象执行操作,会走handler里的办法

对源对象执行操作,不会走handler里的办法

const target = {foo: "bar"}const handler = {    get(target, prop, receiver){ // get()是一个捕捉器,其参数别离代表:指标对象、指标属性、代理对象。每个捕捉器入参不同。        return "handle override"    }}const proxyObj = new Proxy(target,handler)console.log(proxyObj.foo) // "handle override",执行handlerconsole.log(target.foo) // "bar",没有执行handler 

Reflect

what?(Reflect是什么?)

是一个全局的Reflect对象,所有捕捉的办法都有对应的Reflect api办法。它与捕捉器拦挡的办法同名、行为雷同。

Reflect api 不限于捕捉处理程序handler

大多数Reflect api在Object上有对应的办法。

why?(为什么用Reflect?)

有了Reflect后,能够不便写捕捉器。

看例子:

const target = {foo: "bar"}const handler = {    get(target, prop, receiver){        return Reflect.get(...arguments)    }}const proxyObj = new Proxy(target,handler) 

Reflect api会提供一些状态标记。

Reflect.set() ,Reflect.defineProperty()会返回布尔值。

Reflect api可利用一等函数替换操作符。Reflect.has( )

const obj = {name: "cc"}const target = Object.create(obj)target.age = 12if(Reflect.has(target, "name")) { // 亲测和对象的in操作符成果雷同,都能够获取对象原型链上的属性  console.log("wow, I have!")} 

how?(怎么用Reflect?)

以上,写捕捉器的时候能够用,利用它的返回值,在对象上也能够用

代理捕捉器和对应的反射办法

代理能够捕捉13中不同的根底api。

get() 获取属性时

set() 设置属性值

has() 对象执行in操作时

defineProperty( )

getOwnPropertyDescriptor()

deleteProperty()

ownKeys()

getPrototypeOf()

setPropotypeOf()

isExtensible()

preentExtensions()

apply()

construct()

代理模式的几种利用

  1. 跟踪属性拜访

通过捕捉get、set 和has 等操作,能够晓得对象属性什么时候被拜访、被查问。

  1. 暗藏属性
  2. 属性验证

set()外面写捕捉器,验证对象的赋值操作是否非法

例子:

setObjDataEmpty = (paramObj) => {  const proxy = new Proxy(paramObj, {    set(target, prop) {      const oldVal = target[prop]      if(typeof oldVal === "string") { // 字符串,间接赋值        return Reflect.set(...arguments)      }else if(Array.isArray(oldVal)){        return Reflect.set(target, prop, []) // 数组,置空      }else{        return false // 都不是,赋值失败      }    }  })  Object.keys(proxy).forEach(key => {    proxy[key] = ""  })  return proxy} 
  1. 函数和构造函数的参数验证
consructor = () => {  class SetId {    constructor(id) {      this.id = id    }  }  const pSetId = new Proxy(SetId, {    construct(target, argumentList) {      if(argumentList[0] === undefined) {        throw("oh, you must put id!")      }else{        return Reflect.construct(...arguments)      }    }  })  const id1 = new pSetId("1")   console.log(id1)  // {id: '1'}  const id2 = new pSetId() //  Uncaught oh, you must put id!  console.log(id2) } 
  1. 数据绑定与可察看对象
const userList = [];  class User {    constructor(name) {      this.name = name;    }  }  const proxy = new Proxy(User, {    construct() {      const newUser = Reflect.construct(...arguments);      userList.push(newUser);      return newUser;    }  });  new proxy('John');  new proxy('Jacob');  new proxy('Jingleheimerschmidt');  console.log(userList);