JS装饰器是ES7的新语法,浏览器,nodejs不一定支持,需要babel转译。
实验环境
创建一个目录test,结构为:
| 12
 3
 4
 5
 6
 7
 
 | .├── .babelrc
 ├── .npmrc
 ├── lib
 ├── package.json
 └── src
 └── index.js
 
 | 
babel的装饰器配置:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | {
 "presets": [
 "@babel/preset-env"
 ],
 "plugins": [
 [
 "@babel/plugin-proposal-decorators",
 {
 "legacy": true
 }
 ],
 "@babel/plugin-proposal-class-properties"
 ]
 }
 
 | 
依赖包与测试命令:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | {
 "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源:
| 12
 
 | registry=https://registry.npm.taobao.org
 
 | 
安装依赖包:
测试代码
源码都在 src/index.js 中。js装饰器可以装饰的对象:类、属性、方法。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 
 | 
 
 
 
 
 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') {
 if (typeof descriptor.value === 'function') {
 console.log('~~~ decorator of method');
 return descriptor.value;
 } else {
 return {
 ...descriptor,
 writable: 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');
 
 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。

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