资讯专栏INFORMATION COLUMN

es6/es7之Decorator装饰器

yanest / 1625人阅读

摘要:装饰器顾名思义就是装饰某种东西的方法,可以用来装饰属性变量函数类实例方法本质上是个函数。以符开头,函数名称自拟。爱吃苹果装饰器装饰类爱吃苹果结果是这个类本身就可以通过修改类的属性增加属性被装饰的对象可以使用多个装饰器。

@Decorator 装饰器是es7的语法,这个方法对于面向切面编程有了更好的诠释,在一些情境中可以使用,比如路人A的代码实现了一需求,路人B希望用A的方法来实现一个新的需求,而路人A又不希望大改自己的代码,这时候装饰器就能派上用场了。本文就结合情境来说说Decorator的用法。

装饰器顾名思义就是装饰某种东西的方法,可以用来装饰属性、变量、函数、类、实例方法... 本质上是个函数。以@符开头,函数名称自拟。

先看这么一个类↓

@hobby
Class Person {
    constructor() {
        
    }
    @readOnly
    name = "AAA";
    @dealData
    eat() {
        console.log("爱吃苹果")
    }
}

let oP = new Person();

这个函数就用来修饰装饰对象的
function readOnly(proto, key, descriptor) {
    console.log(proto, key, descriptor) //原型, "name ", 一个包含对name属性描述内容的对象
}

descriptor是重头戏,这个对象里包含对装饰对象的描述属性
configurable: true/false, 可配置与否
enumerable: true/false, 可枚举与否
writable: true/false, 可写与否
initializer: 静态属性的value值
value: 非静态属性的value值

上面三个属性好理解,修改也方便,如下
function readOnly(proto, key, descriptor) {
    // 将静态属性name改为只可读,不可写
    descriptor.writable = false;
}

initializer: 静态属性的value值
value: 非静态属性的value值
这两个值就比较有意思了,他们俩的关系是水火不容的,静态属性的装饰器的descriptor里有initializer, 而非静态属性的装饰器其descriptor对象里则是有value这个属性,没有initializer。

function readOnly(proto, key, descriptor) {
    // initializer可以重新赋值
    descriptor.initializer = function () {
        // 函数返回的值就是该静态属性新的值
        return "BBB"
    }
}

function dealData(proto, key, descriptor) {
    // 当我们需要改变函数功能的时候,可以通过这种方式,相当于做个代理,也不会影响原函数
    // 存一下原来的方法
    let oldValue = descriptor.value;
    // 修改(添加)函数的原有功能
    descriptor.value = function() {
        console.log("爱吃橘子");
        oldValue.call(this, arguments);
    }
}

装饰器也是可以传参并且执行返回的函数的
Class Person {
    constructor() {
        
    }
    @readOnly
    name = "AAA";
    @dealData("AAA")
    eat() {
        console.log("爱吃苹果")
    }
}

function dealData(who) {
    return function (proto, key, descriptor) {
        let oldValue = descriptor.value;
        descriptor.value = function() {
            console.log(who + "爱吃橘子"); // AAA爱吃橘子
            return oldValue.call(this, arguments);
        }
    }
}

值得注意的一点是如果这里的eat函数写成箭头函数赋值的形式,就不再是原型上的方法了而是变为静态属性了,要注意一下。

Class Person {
    constructor() {
        
    }
    @readOnly
    name = "AAA";
    @dealData("AAA")
    eat = ()=> {
        console.log("爱吃苹果")
    }
}

装饰器装饰类:

@hobby
Class Person {
    constructor() {
        
    }
    @readOnly
    name = "AAA";
    @dealData
    eat() {
        console.log("爱吃苹果")
    }
}

function hobby(target) {
    console.log(target) // 结果是这个类本身
    // 就可以通过target修改类的属性
    target.name = "CCC";
    // 增加属性
    target.age = 18;
}

被装饰的对象可以使用多个装饰器。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106599.html

相关文章

  • JavaScript设计模式装饰模式

    摘要:原文博客地址装饰器模式为对象添加新功能不改变其原有的结构和功能。手机壳就是装饰器,没有它手机也能正常使用,原有的功能不变,手机壳可以减轻手机滑落的损耗。 原文博客地址:https://finget.github.io/2018/11/22/decorator/ 装饰器模式 为对象添加新功能;不改变其原有的结构和功能。 手机壳就是装饰器,没有它手机也能正常使用,原有的功能不变,手机壳可以...

    tangr206 评论0 收藏0
  • 设计模式装饰者模式

    摘要:相关设计模式装饰者模式和代理模式装饰者模式关注再一个对象上动态添加方法代理模式关注再对代理对象的控制访问,可以对客户隐藏被代理类的信息装饰着模式和适配器模式都叫包装模式关于新职责适配器也可以在转换时增加新的职责,但主要目的不在此。 0x01.定义与类型 定义:装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的...

    chuyao 评论0 收藏0
  • 每天一个设计模式装饰者模式

    摘要:作者按每天一个设计模式旨在初步领会设计模式的精髓,目前采用和两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式原文地址是每天一个设计模式之装饰者模式欢迎关注个人技术博客。 作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式...

    brianway 评论0 收藏0
  • 每天一个设计模式装饰者模式

    摘要:作者按每天一个设计模式旨在初步领会设计模式的精髓,目前采用和两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式原文地址是每天一个设计模式之装饰者模式欢迎关注个人技术博客。 作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式...

    shleyZ 评论0 收藏0
  • ES6 系列我们来聊聊装饰

    摘要:第二部分源码解析接下是应用多个第二部分对于一个方法应用了多个,比如会编译为在第二部分的源码中,执行了和操作,由此我们也可以发现,如果同一个方法有多个装饰器,会由内向外执行。有了装饰器,就可以改写上面的代码。 Decorator 装饰器主要用于: 装饰类 装饰方法或属性 装饰类 @annotation class MyClass { } function annotation(ta...

    eternalshallow 评论0 收藏0

发表评论

0条评论

yanest

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<