乐趣区

关于javascript:Js高级程序设计学习笔记chapter-9

最近公司在组织前端团队学习 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",执行 handler
console.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 = 12
if(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); 
退出移动版