设为首页 加入收藏

TOP

Javascript装饰器的妙用(六)
2018-07-13 06:06:56 】 浏览:321
Tags:Javascript 装饰 妙用
校验的。
然后在validator中继承原有的类对象,并在实例化之后遍历刚才设置的所有校验信息进行验证,如果发现有类型错误的,直接抛出异常。
这个类型验证的操作对于原Class来说几乎是无感知的。


函数参数装饰器


最后,还有一个用于函数参数的装饰器,这个装饰器也是像实例属性一样的,没有办法单独使用,毕竟函数是在运行时调用的,而无论是何种装饰器,都是在声明类时(可以认为是伪编译期)调用的。


函数参数装饰器会接收三个参数:
1.类似上述的操作,类的原型或者类的构造函数
2.参数所处的函数名称
3.参数在函数中形参中的位置(函数签名中的第几个参数)


一个简单的示例,我们可以结合着函数装饰器来完成对函数参数的类型转换:


const parseConf = {}
class Modal {
  @parseFunc
  addOne(@parse('number') num) {
    return num + 1
  }
}


// 在函数调用前执行格式化操作
function parseFunc (target, name, descriptor) {
  return {
    ...descriptor,
    value (...arg) {
      // 获取格式化配置
      for (let [index, type] of parseConf) {
        switch (type) {
          case 'number':  arg[index] = Number(arg[index])            break
          case 'string':  arg[index] = String(arg[index])            break
          case 'boolean': arg[index] = String(arg[index]) === 'true'  break
        }


        return descriptor.value.apply(this, arg)
      }
    }
  }
}


// 向全局对象中添加对应的格式化信息
function parse(type) {
  return function (target, name, index) {
    parseConf[index] = type
  }
}


console.log(new Modal().addOne('10')) // 11


使用装饰器实现一个有趣的Koa封装


比如在写Node接口时,可能是用的koa或者express,一般来说可能要处理很多的请求参数,有来自headers的,有来自body的,甚至有来自query、cookie的。
所以很有可能在router的开头数行都是这样的操作:


router.get('/', async (ctx, next) => {
  let id = ctx.query.id
  let uid = ctx.cookies.get('uid')
  let device = ctx.header['device']
})


以及如果我们有大量的接口,可能就会有大量的router.get、router.post。
以及如果要针对模块进行分类,可能还会有大量的new Router的操作。


这些代码都是与业务逻辑本身无关的,所以我们应该尽可能的简化这些代码的占比,而使用装饰器就能够帮助我们达到这个目的。


装饰器的准备


// 首先,我们要创建几个用来存储信息的全局List
export const routerList      = []
export const controllerList  = []
export const parseList      = []
export const paramList      = []


// 虽说我们要有一个能够创建Router实例的装饰器
// 但是并不会直接去创建,而是在装饰器执行的时候进行一次注册
export function Router(basename = '') {
  return (constrcutor) => {
    routerList.push({
      constrcutor,
      basename
    })
  }
}


// 然后我们在创建对应的Get Post请求监听的装饰器
// 同样的,我们并不打算去修改他的任何属性,只是为了获取函数的引用
export function Method(type) {
  return (path) => (target, name, descriptor) => {
    controllerList.push({
      target,
      type,
      path,
      method: name,
      controller: descriptor.value
    })
  }
}


// 接下来我们还需要用来格式化参数的装饰器
export function Parse(type) {
  return (target, name, index) => {
    parseList.push({
      target,
      type,
      method: name,
      index
    })
  }
}


// 以及最后我们要处理的各种参数的获取
export function Param(position) {
  return (key) => (target, name, index) => {
    paramList.push({
      target,
      key,
      position,
      method: name,
      index
    })
  }
}


export const Body  = Param('body')
export const Header = Param('header')
expor

首页 上一页 3 4 5 6 7 下一页 尾页 6/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇u-boot-1.1.6第1阶段分析之make s.. 下一篇Python 字节码介绍

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目