JavaScript装饰器

本文详细介绍了JavaScript装饰器的原理,如何在类、属性和方法上使用,并通过实例演示了其在类属性只读性上的实现。探讨了Babel配置和转译过程,适合初学者了解装饰器在现代JavaScript开发中的作用。
摘要由CSDN通过智能技术生成

JS装饰器是ES7的新语法,浏览器,nodejs不一定支持,需要babel转译。

实验环境

创建一个目录test,结构为:

.
├── .babelrc
├── .npmrc
├── lib
├── package.json
└── src
    └── index.js

babel的装饰器配置:

# .babelrc
{
    "presets": [
        "@babel/preset-env"
    ],
    "plugins": [
        [
            "@babel/plugin-proposal-decorators",
            {
                "legacy": true
            }
        ],
        "@babel/plugin-proposal-class-properties"
    ]
}

依赖包与测试命令:

# package.json
{
  "name": "testmobx",
  "version": "1.0.0",
  "description": "testmobx",
  "main": "index.js",
  "directories": {
    "lib": "lib"
  },
  "scripts": {
    "build": "babel src -d lib",
    "test": "node lib/index.js"
  },
  "author": "jason",
  "license": "MIT",
  "devDependencies": {
    "@babel/core": "^7.15.5",
    "@babel/cli": "^7.15.0",
    "@babel/plugin-proposal-class-properties": "^7.14.5",
    "@babel/plugin-proposal-decorators": "^7.15.4",
    "@babel/preset-env": "^7.15.6"
  }
}

npm源:

# .npmrc
registry=https://registry.npm.taobao.org

安装依赖包:

cd test
yarn

测试代码

源码都在 src/index.js 中。js装饰器可以装饰的对象:类、属性、方法。

// 装饰器:
// 装饰属性(或方法)时:
// target为属性的类对象,key为属性名字符串,descriptor为属性key的属性描述符对象
// 装饰类时:
// target为类,key与descriptor都是undefined

function readOnly(target, key, descriptor) {
    console.log('target:', target, typeof target);
    console.log('key:', key, typeof key);
    console.log('desc:', descriptor, typeof descriptor);
    if (typeof key === 'string') { // 作为属性或方法装饰器时,key为字符串
        if (typeof descriptor.value === 'function') { // 作为方法装饰器
            console.log('~~~ decorator of method');
            return descriptor.value;
        } else { // 作为属性装饰器
            return {
                ...descriptor,
                writable: false // 覆盖为false
            }
        }
    } else { // 作为类装饰器
        console.log('~~~ decorator of cls');
        return target;
    }
}

class Oatmeal {
    @readOnly viscosity = 20; // 属性装饰器
    constructor(flavor) {
        this.flavor = flavor;
    }
}

var oatmeal = new Oatmeal('Brown Sugar Cinnamon');
// oatmeal.viscosity = 30; // 已设为只读,修改将报错
console.log(oatmeal);

console.log('\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~');

@readOnly
class A {
    constructor() {
        this.a = 111;
    }
};

var a = new A();
console.log(a.a);

console.log('\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~');

class B {
    constructor() {
        this.b = 222;
    }
    @readOnly
    show() {
        console.log(this.b);
    }
}

var b = new B();
b.show();

执行结果

其中initializer与babel相关,当装饰器给属性装饰时,属性描述符对象中会有initializer,为函数,执行descriptor.initializer()后将返回属性的值20。

js-decor1

参考:
https://segmentfault.com/a/1190000021593373

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值