Javascript Decorator

JS的 decorator 已经到了Stage 2 Draft的阶段。并且在 Babel 7得到支持

修饰器其实在其他的语言中已经得到很完善的实现了,比如 Python。修饰器主要的功能是将辅助性的功能和核心功能分开。例如,核心功能可以是主营业务,辅助功能可以是身份验证,信息缓存或者日记功能。这些辅助功能大部分是可以共享的,并且和主要功能没有什么联系,所以解耦和重用是修饰器很重要的功能。

相关信息

不同类型修饰器的应用和分析

类修饰器

使用场景:为类添加静态属性或者方法。
修饰器的参数:

  • target: 类本身

例子:

function language(value) {
    return function(target) {
        target.language = value;
    }
}

@language('English')
class Country {}

console.log(Country.language);
# output: English
实例方法修饰器

应用场景:输出日志,性能计算,权限验证。
修饰器的参数:

  • target:类的prototype。
  • name:要修饰的方法名称。
  • descriptor:该方法的修饰器。

例子:

function beforeFunc(target, name, descriptor) {
    const func = descriptor.value;
    const newFunc = function() {
        console.log(`Before calling: ${name}`);
        const result = func.apply(this, arguments);
        return result;
    }
    return {
        ...descriptor,
        value: newFunc
    }
}

function afterFunc(target, name, descriptor) {
    const func = descriptor.value;
    const newFunc = function() {
        const result = func.apply(this, arguments);
        console.log(`After calling: ${name}`);
        return result;
    }
    return {
        ...descriptor,
        value: newFunc
    }
}

class Medium {
    constructor() {
        this.base = 10;
    }

    @afterFunc
    @beforeFunc
    add(a, b){
        console.log(`Calculating...`);
        return a + b + this.base;
    }
}

// console.log(Country.language);

const m = new Medium();
console.log('Sum: ', m.add(1, 4));
# Output:
# Before calling: add
# Calculating...
# After calling: add
# Sum:  15
实例属性修饰器

使用场景:修改property的属性(writable,enumerable,configurable等),监听属性的变化(watcher)。
修饰器的参数:

  • target:类的prototype。
  • name:要修饰的方法名称。
  • descriptor:该方法的修饰器。

Note: 使用数据描述符和存储描述符定义的属性,它们的descriptor是不一样的。

例子:

  1. 存储描述符: 给属性添加监听器
function observable(target, name, descriptor) {
    const setter = descriptor.set;
    return {
        ...descriptor,
        get: function() {
            console.log(`Before getting '${name}'. '${name}' is ${this.base}`);
            return this.base;
        },
        set: function(value) {
            console.log(`Before setting '${name}'. '${name}' is ${this.base}`);
            setter.call(this, value);
            return true;
        }
    };
}

class Medium {
    @observable
    get count () {
        return this.base;
    };
    set count (value) {
        this.base = value;
    };

    constructor() {
        this.base = 10;
    }
}

const m = new Medium();
m.count += 20;
console.log('Count: ', m.count);
# Output:
# Before getting 'count'. 'count' is 10
# Before setting 'count'. 'count' is 10
# Before getting 'count'. 'count' is 30
# Count:  30
  1. 数据描述符: 将属性设置为只读
function readonly(target, name, descriptor) {
    descriptor.writable = false;
    return descriptor;
}
class Medium {
    @readonly
    age = 18;
}
const m = new Medium();
m.age = 28;

# throw an error: 
# TypeError: Cannot assign to read only property 'age' of object '#<Medium>'

Desugar

说到底JS中的修饰器只是一种语法糖,最终还是由解释器翻译成一般的JS语法。JS的修饰器主要依赖于 Object.defineProperty 功能,当解释器遇到了 @decorator 的语法时,就会调用这个修饰器函数对属性(方法)的描述符(descriptor)进行操作,然后将修饰过的 descriptor 重新定义属性。
具体的转义可以查看:https://github.com/wycats/javascript-decorators#desugaring

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266