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建立一个代理对象。api

const proxyObj = new Proxy(targetObj, handlerObj)

能够给对象obj建立一个代理。数组

why?(为何用Proxy?)

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

好比:ide

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方法。它与捕获器拦截的方法同名、行为相同。this

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);
相关文章
相关标签/搜索