JS装饰器是ES7的新语法,浏览器,nodejs不一定支持,需要babel转译。
实验环境
创建一个目录test,结构为:
1 2 3 4 5 6 7
   | . ├── .babelrc ├── .npmrc ├── lib ├── package.json └── src     └── index.js
   | 
 
babel的装饰器配置:
1 2 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"     ] }
 
  | 
 
依赖包与测试命令:
1 2 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源:
1 2
   |  registry=https://registry.npm.taobao.org
 
  | 
 
安装依赖包:
测试代码
源码都在 src/index.js 中。js装饰器可以装饰的对象:类、属性、方法。
1 2 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