js修饰器

一、什么是js修饰器

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

二、使用

1、对类进行修饰

@testable
class MyTestableClass {
  // ...省略
}

function testable(target) {
  target.isTestable = true
}
MyTestableClass.isTestable // true

如上代码所示,testable就是一个修饰器,它对MyTestableClass进行了修改,添加了一个isTestable 属性。
并且可以看到,修饰器testable的第一个参数就是所修饰的类,如果需要传入更多参数,则需要在修饰器内再写一层函数。

function testable(isTestable) {
  return function(target) {
    target.isTestable = isTestable;
  }
}

@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true

@testable(false)
class MyClass {}
MyClass.isTestable // false

上面代码中的修饰器testable就可以接收其他参数了,而被修饰的类则作为它返回出来的函数的参数。

注意,修饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,修饰器能在编译阶段运行代码。也就是说,修饰器本质就是编译时执行的函数

以上是对类添加一个静态属性的例子,如果需要添加实例属性(即对类的实例也都进行修改),则需要对类的prototype对象进行操作。

function testable(target) {
  target.prototype.isTestable = true;
}

@testable
class MyTestableClass {}

let obj = new MyTestableClass();
obj.isTestable // true

这样对类的prototype对象进行了修改,使得类的实例也都继承了修改的属性。

2、对类的方法进行修改

当修饰器对类的方法进行修改时,可以接收三个参数,分别是类的原型对象(即类的prototype对象),修饰器的本意是要“修饰”类的实例,但是这个时候实例还没生成,所以只能去修饰原型(这不同于类的修饰,那种情况时target参数指的是类本身);第二个参数是所要修饰的属性名(即被修改的方法名),第三个参数是该属性的描述对象(即被修改的方法本身)。

class User {
    @readonly
    getName() {
        return 'Hello World'
    }
}

// readonly修饰函数,对方法进行只读操作
function readonly(target, name, descriptor) {
    descriptor.writable = false //将方法的可写属性设为false,即不可写
    return descriptor
}

let u = new User()
// 尝试修改函数,因为已经设置为不可写,所以在控制台会报错
u.getName = () => {
    return 'I will override'
}

如果要修改方法的内容,则可以用value属性

descriptor.value = 'function (){ console.log('Hello decorator') }'

这样执行方法时,会输出Hello decorator,而非'I will override
如果同一个方法有多个修饰器,会像剥洋葱一样,先从外到内进入,然后由内向外执行。(即写在后面的先执行)

3、为什么修饰器不能用于函数?

修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。类是不会提升的,所以就没有这方面的问题。

4、mixin

在修饰器的基础上,可以实现Mixin模式。所谓Mixin模式,就是对象继承的一种替代方案,中文译为“混入”(mix in),意为在一个对象之中混入另外一个对象的方法。
一个通用minxin脚本

export function mixins(...list) {
  return function (target) {
    Object.assign(target.prototype, ...list);
  };
}

使用:

import { mixins } from './mixins';

const Foo = {
  foo() { console.log('foo') }
};

@mixins(Foo)
class MyClass {}

let obj = new MyClass();
obj.foo() // "foo"

不过,上面的方法会改写MyClass类的prototype对象,如果不喜欢这一点,也可以通过类的继承实现 Mixin。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 修饰器(Decorator)是一个函数,用来修改类的行为。这是ES7的一个提案,目前Babel转码器已经支持。本文...
    码出我天地阅读 7,420评论 2 3
  • 本文为阮一峰大神的《ECMAScript 6 入门》的个人版提纯! babel babel负责将JS高级语法转义,...
    Devildi已被占用阅读 2,029评论 0 4
  • decorator是ES7引入的功能,它是一个函数,用来修改类甚至于是方法的行为。 类的修饰 一个简单的栗子: @...
    youngss阅读 289评论 0 0
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,350评论 0 3
  • 1 鱼子有个英雄梦,从小就有。 “鱼子,走啦走啦,去那个小教堂探险咯。”大白带着一波院里的小伙伴在楼下吆喝。 此刻...
    归桦阅读 406评论 2 5