美文网首页前端笔记
Decorator 修饰器

Decorator 修饰器

作者: faremax | 来源:发表于2017-10-03 21:15 被阅读12次

修饰器

修饰器是 ES7 提出的一个提案,用来修改类的行为。目前需要 babel 才可以使用。它最大的特点是:可以在编译期运行代码!其本质也就是在编译器执行的函数。其执行格式如下:

@decorator    //decorator 是修饰器名,即函数名
class A{}
//相当于
class A{}
A = decorator(A) || A;

修饰器函数接受3个参数,依次是目标函数、属性名(可忽略)、该属性的描述对象(可忽略)。

function test(target){
  target.isTestable = true;               //利用修饰器给类添加静态属性
  target.prototype.isTestable = true;     //利用修饰器给类添加动态属性
}

@test
class A{}

console.log(A.isTestable);       //true
console.log(new A().isTestable);   //true

例如之前的 mixin 可以用修饰器实现一个简单的版本:

function mixins(...list){
  return function(target){
    Object.assign(target.prototype, ...list);
  }
}
var Foo = {
  foo(){console.log("foo");}
};
@mixins(Foo)
class Cla{}
let obj = new Cla();
obj.foo();     //"foo"

修饰器不仅仅可以修饰类,还可以修饰类的属性和方法:

function readonly(target, name, descriptor){
  descriptor.writable = false;
  return descriptor;
}

class Person{
  constructor(name, age, tel){
    this.name = name;
    this.id = id;
  }
  @readonly
  id(){return this.id};
}

当然也可以同时调用2个修饰器:

function readonly(target, name, descriptor){
  descriptor.writable = false;
  return descriptor;
}
function nonenumerable(target, name, descriptor){
  descriptor.enumerable = false;
  return descriptor;
}

class Person{
  constructor(name, age, tel){
    this.name = name;
    this.id = id;
  }
  @readonly
  @nonenumerable
  id(){return this.id};
}

使用修饰器应该注意:虽然类本质是个函数,但修饰器不能用于函数,因为函数具有声明提升。

core-decroators.js

这是个三方模块,使用import {function Namelist} from 'core-decroators';引入。它提供了几个常见的修饰器:

  • @autobind
    是对象中的 this 始终绑定原始对象:
class Person{
  @autobind
  whoami(){
    return this;
  }
}
let person = new Person();
let getPerson = person.getPerson;

getPerson() === person;    //true
  • @readonly
    使得属性方法只读
class Person{
  @readonly
  id = gen();     //gen 是一个计数器
}
var p = new Person()
p.id = 123;   //Cannot assign to read only property 'id' of [object Object]
  • @override
    检查子类方法是否正确的覆盖了父类的同名方法,如果不正确会报错
class Person{
  work(){console.log("I am working");}
}
class Coder extends Person{
  @override
  work(){console.log("I am coding");}   //如果不正确会在这里报错
}
  • @deprecate(也作: @deprecated)
    在控制台显示一条 warning,表示该方法不久后将被废除,接受一个可选的参数作为警告内容, 接受第二个参数(对象)表示更多信息
class Person{
  @deprecate
  facepalm(){}

  @deprecate('We stopped facepalming')
  facepalmHard(){}

  @deprecate('We stopped facepalming', {url:'http://balabala.com'})
  facepalmHarder(){}
}
  • @suppressWarnings
    抑制 deprecate 修饰器导致调用 console.warn(), 但异步代码发出的除外。
class Person{
  @deprecate
  facepalm(){}

  @supressWarnings
  facepalmWithoutWarning(){
    this.facepalm();
  }
}
let p = new Person();
p.facepalm();    //控制台显示警告
p.facepalmWithoutWarning();    //没有警告

其它第三方修饰器

此外还有一些库提供一些其他功能,比如 Postal.js(Github)中的 @publish, 可以在函数调用时发布一个事件:

import publish from "../to/decorators/publish";

class FooComponent{
  @publish("foo.some.message", "component")
  someMethod(){}

  @publish("foo.some.other", "")
  anotherMethod(){}
}

再比如 Trait(Github), 和 mixin 功能类似,提供了更强大的功能:防止同名冲突,排除混入某些方法,为混入方法起别名等

import {traits} from 'traits-decorator'

class TFoo{
  foo(){console.log("foo1")}
}
class TBar{
  bar(){console.log("bar")}
  foo(){console.log("foo2")}
}

@traits(TFoo, TBar)       //会报错,因为这两个类中有同名方法
class MyClass{}

let obj = new MyClass();
//如果没有第八行的同名方法,输出如下
obj.foo();   //"foo1"
obj.bar();   //"bar"

但是我们可以修改上面第11行排除这个 foo,让它可以被覆盖:

@traits(TFoo, TBar::excludes('foo'))
class MyClass{}

也可重命名同名方法:

@traits(TFoo, TBar::alias(foo:'aliasFoo'))
class MyClass{}

当然绑定运算符可以链式调用:

//假设还有个同名的 baz 方法
@traits(TFoo, TBar::excludes('foo')::alias(baz:'aliasBaz'))
class MyClass{}

//另一种写法
@traits(TFoo, TBar::as({excludes: ['foo'], alias: {baz:'aliasBaz'}}))
class MyClass{}

相关文章

  • 27- ES6 装饰器

    1、类的修饰 decorator(target) {} 许多面向对象的语言都有修饰器(Decorator)函数,...

  • @修饰器Decorator

    编前语 修改类的行为 修饰类、修饰类的属性 ES7的一个提案 类的改变在代码编译时发生,不是在运行时 babel转...

  • Decorator 修饰器

    修饰器 修饰器是 ES7 提出的一个提案,用来修改类的行为。目前需要 babel 才可以使用。它最大的特点是:可以...

  • es6学习笔记整理(十六)Decorators

    Decorator修饰器 修饰器是一个函数用来修改类的行为: 1、修饰器是一个函数 2、修改行为 3、修改类的行为...

  • (二)20.Decorator19-08-15

    Decorator - 1基本概念 Decorator(修饰器)是一个函数用来修改类的行为,(扩展类的功能,只在类...

  • ES6(十七):ES2017中的修饰器Decorator

    前面的话   修饰器(Decorator)是一个函数,用来修改类的行为。本文将详细介绍ES2017中的修饰器Dec...

  • es7装饰器(修饰符/语法糖)的使用详解以及使用场景

    Decorator(修饰器),用来修改原类/方法的功能。 我们对装饰器并不陌生,例如 dvajs的 @connec...

  • JavaScript(ES6) - Decorator

    类的修饰 修饰器(Decorator)是一个函数,用来修改类的行为。这是ES7的一个提案,目前Babel转码器已经...

  • Python 中修饰器

    修饰器就是一个返回函数的高阶函数 如果decorator本身需要传入参数,那就需要编写一个返回decorator的...

  • js修饰器

    一、什么是js修饰器 修饰器(Decorator)是ES7的一个提案,它是用于对类和类的方法进行处理的函数 二、使...

网友评论

    本文标题:Decorator 修饰器

    本文链接:https://www.haomeiwen.com/subject/yxsfyxtx.html