优秀装饰器源码学习(二)

简介: 优秀装饰器源码学习(二)

前言


上一篇文章:优秀装饰器源码学习(一):time

本篇先学习一些初级较简单的@deprecate , @readonly , @enumerable , @nonconfigurable


deprecate


用于提示XX API/方法已经被弃用


使用示例


使用如下,通过一个简单的 @deprecate 即可在函数执行的时候抛出 API已被弃用的警告


其中 deprecatedeprecated效果一致,只是不同的别名


export { default as deprecate, default as deprecated } from './core/deprecate'


import { deprecate, deprecated } from '../index'
class Test {
    @deprecate()
    sayHello1() {
        console.log('hello 1');
    }
    @deprecated('API弃用警告')
    sayHello2() {
        console.log('hello 2');
    }
    @deprecate('API弃用警告',{url:'https://www.baidu.com'})
    sayHello3() {
        console.log('hello 3');
    }
}
const t = new Test()
t.sayHello1()
t.sayHello2()
t.sayHello3()


执行效果


网络异常,图片无法展示
|


函数结构


传入参数:

  • msg:有默认内容
  • options:通过url属性进一步指定文档链接


const DEFAULT_MSG = 'This function will be removed in future versions.';
interface Options{
    url?:string
}
export default function deprecate(msg = DEFAULT_MSG, options:Options = {}) {
    return function (target, key, descriptor) {
    }
}


最终实现


const DEFAULT_MSG = 'This function will be removed in future versions.';
interface Options{
    url?:string
}
export default function deprecate(msg = DEFAULT_MSG, options:Options = {}) {
    return function (target, key, descriptor) {
        // 如果被装饰对象不是函数,直接抛出错误
        if (typeof descriptor.value !== 'function') {
            throw new SyntaxError('Only functions can be marked as deprecated');
        }
        // 生成方法的签名(反应来自与xx类xx方法)
        const methodSignature = `${target.constructor.name}#${key}`;
        // 如果有线上地址的文档描述原因,则展示一下这个地址
        if (options.url) {
            msg += `\n\n    See ${options.url} for more details.\n\n`;
        }
        return {
            ...descriptor,
            value: function deprecationWrapper() {
                // 打印警告信息
                console.warn(`DEPRECATION ${methodSignature}: ${msg}`);
                // 执行函数
                return descriptor.value.apply(this, arguments);
            }
        };
    }
}


readonly


将指定属性变为只读,即不可在实例化后更改属性的内容


使用示例


使用如下,通过一个简单的 @readonly 即可将目标属性变为只读


import { readonly } from '../index';
class Test {
    hello1(){
        console.log('hello1');
    }
    @readonly
    hello2(){
        console.log('hello2');
    }
}
const t = new Test();
t.hello1 = function(){
    console.log('1');
}
t.hello1()
t.hello2 = function(){
    console.log('2');
}
t.hello2()


执行效果


网络异常,图片无法展示
|


函数实现


无需额外传参,直接通过修改装饰对象的descriptor上的writable属性为false实现


export default function readonly(target, key, descriptor) {
    descriptor.writable = false
    return descriptor
}


enumerable、nonenumerable、enumable


更改装饰对象的enumerable属性值


使用示例


import enumable from "../core/enumable";
import enumerable from "../core/enumerable";
import nonenumerable from "../core/nonenumerable";
class Test {
    @nonenumerable
    a(){
    }
    @enumerable
    b(){
    }
    @enumable(false)
    c(){
    }
}
console.log(Object.getOwnPropertyDescriptor(Test.prototype,'a')?.enumerable === false); // true
console.log(Object.getOwnPropertyDescriptor(Test.prototype,'b')?.enumerable === true);  // true
console.log(Object.getOwnPropertyDescriptor(Test.prototype,'c')?.enumerable === false); // true
console.log(Object.keys(Test.prototype)); // ['b']


实现

这个比较简单就是修改一下装饰对象的enumerable


enumerable


export default function enumerable(target, key, descriptor) {
    descriptor.enumerable = true
    return descriptor
}


nonenumerable


export default function nonenumerable(target, key, descriptor) {
    descriptor.enumerable = false
    return descriptor
}


enumable


export default function enumable(v = true) {
    return function (target, key, descriptor) {
        descriptor.enumerable = v
        return descriptor
    }
}


nonconfigurable


设置装饰对象的configurable属性为false


当且仅当 configurable 为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。


使用示例


import { nonconfigurable } from "../index";
class Test {
    @nonconfigurable
    a(){
    }
    b(){
    }
}
let prototype:any = Test.prototype
delete prototype.b
console.log(Object.keys(Test.prototype)); // ['a']
delete prototype.a // 抛出错误: Cannot delete property 'a' of #<Test>
console.log(Object.keys(Test.prototype));


实现


这个依旧比较简单就是修改一下装饰对象的configurable


export default function nonconfigurable(target, key, descriptor) {
    descriptor.configurable = false
    return descriptor
}


未完待续


下一篇将学习:


  • @mixin:混入方法到类中
  • @lazyInitialize:在使用的时候才初始化目标属性
  • @debounce:防抖
  • @throttle:节流
相关文章
|
应用服务中间件 nginx
nginx优化:URI过长或request header过大导致400或414报错
当出现URI过长或请求头过大导致400或414报错时,可以通过以下方式对Nginx进行优化: 1. 调整client_max_body_size参数:该参数用于限制请求体的大小。默认情况下,Nginx的client_max_body_size参数设置为1M。如果请求体超过这个大小,Nginx会返回400错误。您可以根据实际需求适当增加这个值,例如设置为10M或更大。 ``` http { client_max_body_size 10M; } ``` 2. 调整large_client_header_buffers参数:该参数用于调整请求头缓冲区的大
8115 0
|
JSON 前端开发 数据格式
【前后端异常】http/https post请求 返回415错误状态码的解决方法
【前后端异常】http/https post请求 返回415错误状态码的解决方法
7693 0
|
JavaScript 前端开发 Docker
如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
通过这些步骤,可以确保您的Next.js应用在多核服务器上高效运行,并且在Docker环境中实现高效的容器化管理。
1268 44
|
Web App开发 缓存 UED
如何设置浏览器的缓存策略?
【10月更文挑战第23天】通过合理地设置浏览器的缓存策略,可以在提高网页性能、减少网络流量的同时,确保用户能够获取到最新的内容,从而提升用户体验和网站的性能优化效果。
1325 60
由于没有公钥,无法验证下列签名: NO_PUBKEY 23E7166788B63E1E
由于没有公钥,无法验证下列签名: NO_PUBKEY 23E7166788B63E1E
811 0
|
存储 NoSQL Java
解决 MISCONF Redis is configured to save RDB snapshots 异常详解
解决 MISCONF Redis is configured to save RDB snapshots 异常详解
3826 0
解决 MISCONF Redis is configured to save RDB snapshots 异常详解
看淡你的权力
组织结构的位置只是一种工作报告形式,代表的是需要去承担不同的责任,至于“权力”的大小那是另外一个问题。公司可能因为很多的原因,进行组织结构调整,老板也许仅仅是希望多一个代理人进行监督而已。
797 0
|
1天前
|
人工智能 自然语言处理 JavaScript
2026年Windows+Ollama本地部署OpenClaw保姆级教程:本地AI Agent+阿里云上快速搭建
2026年OpenClaw凭借本地部署、私有化运行的特性,成为打造个人智能体的核心工具,而Ollama作为轻量级本地大模型管理工具,能让OpenClaw摆脱对云端大模型的依赖,实现**本地推理、数据不泄露、全流程私有化**的智能体验。本文基于Windows 11系统,从硬件环境准备、Ollama安装与模型定制、OpenClaw部署配置、技能扩展到常见问题排查,打造保姆级本地部署教程,同时补充阿里云OpenClaw(Clawdbot)快速部署步骤,兼顾本地私有化需求与云端7×24小时运行需求,文中所有代码命令均可直接复制执行,确保零基础用户也能快速搭建属于自己的本地智能体。
2925 12
|
12天前
|
人工智能 自然语言处理 监控
OpenClaw skills重构量化交易逻辑:部署+AI全自动炒股指南(2026终极版)
2026年,AI Agent领域最震撼的突破来自OpenClaw(原Clawdbot)——这个能自主规划、执行任务的智能体,用50美元启动资金创造了48小时滚雪球至2980美元的奇迹,收益率高达5860%。其核心逻辑堪称教科书级:每10分钟扫描Polymarket近千个预测市场,借助Claude API深度推理,交叉验证NOAA天气数据、体育伤病报告、加密货币链上情绪等多维度信息,捕捉8%以上的定价偏差,再通过凯利准则将单仓位严格控制在总资金6%以内,实现低风险高频套利。
6474 58