装饰器的练习(二)

52 阅读2分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

前言

ES7的与类相关的新语法,通过添加@方法名对对象进行装饰包装,返回被包装的对象。下面我将给几个实例来加深理解学习。

1.类装饰器

对于类属性或方法的装饰本质是操作其描述符,理解成是Object.defineProperty(obj, prop, descriptor)的语法糖

(Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象)

  • 语法:Object.defineProperty(obj, prop, descriptor)
    • obj:要在其上定义属性的对象。
    • prop:要定义或修改的属性的名称。
    • descriptor:将被定义或修改的属性描述符。
    • 返回值:被传递给函数的对象。

实例:实现给类添加属性和方法

export function CreatePerson(isLike) {
    return function(target, key, descripto) {
        target.prototype.eat = () => '吃苹果'
        target.isLike = true;
    }
}

@CreatePerson(true)
class Person {}
let p1: any = new Person();
console.log(Person.isLike); // true
console.log(123, p1.eat()); // '吃苹果'

2. 属性装饰器

装饰属性和方法 实例:实现一个缓存的装饰器

这种缓存的思想就类似于react的useCallback或者useMemo

//采用一个Map来进行存储,这个这个缓存存在了缓存中,页面刷新后将会失效
const cacheMap = new Map();

export function EnableCache(target: any, name: string, descriptor: PropertyDescriptor) {
   //获取原型对象的value
    const oldValue = descriptor.value;
    
    descriptor.value = async function(...args: any) {
        //用cacheKey来判断,之前是否已经存在了,有了就替换新的;没有就直接存储
        const cacheKey = name + JSON.stringify(args);
        if (!cacheMap.get(cacheKey)) {
            const cacheValue = Promise.resolve(oldValue.apply(this, args)).catch((_) => cacheMap.set(cacheKey, null));
            cacheMap.set(cacheKey, cacheValue);
        }
        return cacheMap.get(cacheKey);
    };
    return descriptor;
}

注意:装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升,如果一定要装饰函数,可以采用高阶函数的形式直接执行。

结束语

希望大家能够喜欢我的文章,我真的很用心在写,也希望通过文章认识更多志同道合的朋友。

最后伙伴们,如果喜欢我的可以给点一个小小的赞👍或者关注➕都是对我最大的支持。