优秀装饰器源码学习(三)@mixin,@lazyInitialize

简介: 优秀装饰器源码学习(三)@mixin,@lazyInitialize

前言


通过前两篇文章《优秀装饰器源码学习(一):time》,《优秀装饰器源码学习(二)》学习了


@time,@deprecate, @readonly, @enumerable, @nonconfigurable等基础的装饰器


本文和大家一起学习几个稍微复杂一点的装饰器:


  • @mixin:混入方法到类中
  • @lazyInitialize:在使用的时候才初始化目标属性


@mixin


混入对象中的方法到类中


使用示例


通过@mixin(obj1,obj2,obj3,..)就能将对象中的属性,挂载到目标类的原型上

就行Vue中通过mixin混入一些公共的方法


import { mixin } from '../index'
const obj1 = {
    logA() {
        console.log(this.a);
    }
}
const obj2 = {
    printKeys() {
        console.log(Object.keys(this));
    }
}
@mixin(obj1, obj2)
class Test {
    public a = 1
}
const t: any = new Test()
t.logA() // 1
t.printKeys() // ['a']


函数结构


传入参数:

  • objs:rest参数,支持传入多个对象进行混入的操作


function handleClass(target, mixins) {
    if (!mixins.length) {
        throw new SyntaxError(`@mixin() class ${target.name} requires at least one mixin as an argument`);
    }
}
export default function mixin(...objs) {
    return function (target) {
        return handleClass(target, objs)
    }
}


实现原理


  • 类装饰器第一个参数target标识装饰的类
  • target.prototype标识类的原型
  • 遍历传入的对象,通过Object上的getOwnPropertyNamesgetOwnPropertyDescriptor方法分别获取目标对象的自有属性(不包括Symbol属性)与指定属性的描述符
  • 在通过Object.defineProperty实现在Class.prototype上进行拓展


handleClass的完整实现


/**
 * 获取对象上的每个属性的描述符
 */
function getOwnPropertyDescriptors(obj) {
    const descs = {};
    Object.getOwnPropertyNames(obj).forEach(key => {
        descs[key] = Object.getOwnPropertyDescriptor(obj, key)
    })
    return descs;
}
function handleClass(target, mixins) {
    if (!mixins.length) {
        throw new SyntaxError(`@mixin() class ${target.name} requires at least one mixin as an argument`);
    }
    for (let i = 0; i < mixins.length; i++) {
        const descs = getOwnPropertyDescriptors(mixins[i])
        const keys = Object.getOwnPropertyNames(mixins[i])
        for (let j = 0; j < keys.length; j++) {
            const key = keys[j];
            if (!target.prototype.hasOwnProperty(key)) {
                Object.defineProperty(target.prototype, key, descs[key])
            }
        }
    }
}


lazyInitialize


懒加载指定属性,即在使用的时候才初始化目标属性


使用示例


将需要懒执行的逻辑放入到@lazyInitialize之中


import { lazyInitialize } from "..";
function getMaxArray(str=''){
    console.log(str,'init huge array');
    return new Array(100)
}
class Test{
    @lazyInitialize(()=>getMaxArray('a'))
    public a
    public b = getMaxArray('b')
}
const t = new Test()
const k = new Test()
k.a


运行结果


b init huge array
b init huge array
a init huge array


实现原理


  • 使用闭包存储值初始化的函数
  • 修改属性的get行为,当调用get的时候再执行初始化逻辑
  • 将初始化后的内容使用中间变量暂存
  • 再次get调用属性的时候,直接返回暂存的内容


函数实现


function createDefaultSetter(key) {
    return function set(newValue) {
        Object.defineProperty(this, key, {
            configurable: true,
            writable: true,
            enumerable: true,
            value: newValue
        });
        return newValue;
    };
}
export default function lazyInitialize(initializer): any {
    let t
    return function (target, key) {
        return {
            get() {
                t = t === undefined? initializer.call(this) : t
                return t;
            },
            set: createDefaultSetter(key)
        }
    }
}


未完待续


下一篇将学习:

  • @debounce:防抖
  • @throttle:节流
相关文章
|
5月前
|
缓存 Windows
电脑小白必看:C 盘满了怎么清理?软件搬到 D 盘的超简单步骤
C盘空间不足导致电脑卡顿?试试这些方法优化!首推FreeMove工具,不到1MB,简单两步搬软件,解放C盘空间。此外,清理临时文件、转移用户文件夹至D盘、调整虚拟内存位置、使用符号链接等技巧也能有效缓解压力。注意:系统核心目录不可移动,操作前请备份重要数据,确保安全!
466 5
|
Web App开发 测试技术 API
Web自动化测试框架(基础篇)--Selenium WebDriver工作原理和环境搭建
本文详细介绍了Selenium WebDriver的工作原理,包括其架构、通信机制及支持的浏览器,并指导读者如何在Python环境下搭建Selenium WebDriver的测试环境,从安装Python和Selenium库到编写并运行第一个自动化测试脚本。
722 0
表格高度根据内容自适应的瀑布流
表格高度根据内容自适应的瀑布流
197 1
|
关系型数据库 MySQL
MySQL 的 union 和union all 的区别
【5月更文挑战第4天】MySQL 的 union 和union all 的区别
615 7
Linux磁盘配额
在Linux系统中,当用户的空间占用接近或超过预设的软限制时,系统会警告用户磁盘空间将满。软限制是允许用户使用的磁盘空间的最大值,在此限制下,用户仍有宽限期来减少空间使用。如果在宽限期内用户未减少空间占用,达到硬限制,软限制将升级为硬限制。硬限制是用户可以使用的绝对最大值。默认的宽限期是7天,如果超过这个期限,用户的空间限制会立即降低到硬限制。
|
存储 弹性计算 安全
阿里云服务器租用价格参考,2核4G、4核8G、8核16G最新收费标准
阿里云服务器2核4G、4核8G、8核16G配置租用价格参考,2024年阿里云产品再一次降价,降价之后2核4G配置按量收费最低收费标准为0.225元/小时,按月租用标准收费标准为68.0元/1个月。4核8G配置的阿里云服务器按量收费标准最低为0.45元/小时,按月租用标准收费标准为216.0元/1个月。8核16G配置的阿里云服务器按量收费标准最低为0.9元/小时,按月租用标准收费标准为432.0元/1个月。云服务器实例规格的地域和实例规格不同,收费标准不一样,下面是2024年阿里云服务器2核4G、4核8G、8核16G配置的最新租用收费标准。
阿里云服务器租用价格参考,2核4G、4核8G、8核16G最新收费标准
|
人工智能 IDE JavaScript
分享一个很好用的代码辅助AI工具CodeGeeX2
分享一个很好用的代码辅助AI工具CodeGeeX2
398 1
|
算法 Unix Shell
【Shell 命令集合 系统管理 】Linux 显示或设置系统时间和日期 date命令 使用指南
【Shell 命令集合 系统管理 】Linux 显示或设置系统时间和日期 date命令 使用指南
533 0
|
存储 Windows
Cheat Engine基本使用方法
Cheat Engine基本使用方法
1496 2
|
存储 人工智能 API
Elasticsearch实战:常见错误及详细解决方案
Elasticsearch实战:常见错误及详细解决方案