6.28学习 babel转换,es6的装饰器

1.babel转换

1.1出现问题

先来一段代码,运行,有可能是会报错的,为什么呢?因为JS以前只能运行在浏览器中,Node.js 出现之后,不管是服务器上,还是我们自己的的笔记本上,只要安装了 Node.js 就可以运行 JS 代码了。所以是node帮我们运行了代码的。
有可能报错的原因是node的版本很多,这种很新的语法可能在低版本的node版本是不支持的。

class Animal{
   static flag = '哺乳类';
   constructor(){
      this.name = 'XXX'
   }
   say(){
      console.log('say')
   }
}
let animal1 = new Animal();
console.log(animal1,Animal.flag)
animal1.say()

目前我的node版本是14.15.1,是可以支持的
在这里插入图片描述
但是我把node的版本降为8.17.0的话,就会报错的
在这里插入图片描述
我们下面就以8.17.0的版本演示下面的内容。

1.2babel转换

如果版本不支持的话,我们就可以用babel/将我们的高级代码(es7等)转换为es5代码。这里就要装一个包babel-cli。但是babel-cli是以前的写法了,现在一般是@babel/cli。执行命令:

npm init  npm install @babel/cli --dev

安装后会发现在node_modules目录下多一个.bin目录
在这里插入图片描述
这里再引入一个 npx命令,它是node5.2版本以上会提供的,帮我们执行node_modules/.bin目录下的文件。那我们执行下 npx babel试一下
在这里插入图片描述
看到报错了,未找到@babel/core模块。那我们再npm install @babel/core --dev把它装上后再试一下npx babel
在这里插入图片描述
还是报错,语法不对这里是。要告诉它编译的是哪个文件和编译后要变成什么文件。
在这里插入图片描述
会发现确实目录下多了个编译后的文件,我这里是es5.js。但是打开一看发现,跟原来编译前的代码一摸一样!!!那不是没编译嘛。
其实是 @babel/core只做转换的动作,但是你还需要告诉它转换的规则是什么。这里就要在你项目的最外层,和node_modules同级目录建一个.babelrc文件。
我们下载包@babel/preset-env,并且在.babelrc中配置

{
   "presets": ["@babel/preset-env"],
   "plugins": []
}

然后再执行我们的npx命令(我的是npx babel .\index.js -o ./es5.js),发现编译出来的文件不一样了!!!

在这里插入图片描述
再运行
在这里插入图片描述
但是这个@babel/preset-env包也只能转换已定案的语法,像更高级的语法,例如装饰器,static xxx = 'xx’等还是无法转译的。
@babel/plugin-proposal-class-properties 这个包就是用来转换static xxx = ‘xx’(类的属性的) 不支持的话可以安装。
其实npx的执行顺序可以看作 @babel/cli ==> @babel/core ==> 转换(读取.babelrc中的配置)

2.装饰器

2.1类装饰器

装饰器写在类外面的是类装饰器

//装饰器 mobx nest vue 
//装饰器可以修饰 类的属性 类的原型上的方法
//修饰的时候就是把这个类 属性... 传递给修饰的函数
@flag
class Animal{
   // static flag = '哺乳类';
   name = 'XXX'
   say(){
      console.log('say')
   }
}

function flag(Constructor){
   Constructor.type = '哺乳类'
}
console.log(Animal.flag)

类装饰器有个参数,就是会被装饰的类
这里执行npx命令就会报错
在这里插入图片描述
他还给了提示,那我们就把@babel/plugin-proposal-decorators装上,并且在.babelrc中配置

{
   "presets": ["@babel/preset-env"],
   "plugins": ["@babel/plugin-proposal-decorators"]
}

再来npx,还是报错。。。
在这里插入图片描述
,babelrc配置写错了

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

再npx可以的了
上面的装饰器是可以传参的,例如

@flag('哺乳类')
function flag(value){
   return function (Constructor) {
      Constructor.type = value
   }
}

其实@flag可以看成个语法糖

@flag('哺乳类')
flag('哺乳类')(Animal)
function flag(value){
   return function (Constructor) {
      Constructor.type = value
   }
}

2.2方法装饰器

写在类里面的装饰器就是方法装饰器,他有三个参数的。第一个参数是类的原型对象,上例是Animal.prototype,装饰器的本意是要“装饰”类的实例,但是这个时候实例还没生成,所以只能去装饰原型(这不同于类的装饰,那种情况时target参数指的是类本身);第二个参数是所要装饰的属性名,第三个参数是该属性的描述对象。

@flag
class Animal{
   // static flag = '哺乳类';
   @readonly
   name = 'XXX'
   say(){
      console.log('say')
   }
}

function flag(Constructor){
   Constructor.type = '哺乳类'
}
console.log(Animal.type)

//直接编译会出错的 npx babel .\class-decorator.js -o es5.js

//1)类的静态属性

//2)类的属性(实例上的属性)

// function readonly() {
//    console.log(arguments)//有三个参数 Animal的实例 属性 配置项({
  configurable: true,
  enumerable: true,
  writable: true,
  initializer: [Function: initializer]
})
// }
function readonly(target,property,descriptor) {
   console.log(target == Animal.prototype)
}

所以把这段代码编译后执行会报错,
在这里插入图片描述
因为这个时候实例还没生成,这样写就不会报错

  setTimeout(function () {
    console.log(target == Animal.prototype);
  });

方法装饰器可以修改属性的描述对象(descriptor),然后被修改的描述对象再用来定义属性。
我们在方法前面定义一个装饰器,它的第三个参数是不一样的

//装饰器 mobx nest vue 
//装饰器可以修饰 类的属性 类的原型上的方法
//修饰的时候就是把这个类 属性... 传递给修饰的函数
@flag
class Animal{
   // static flag = '哺乳类';
   @readonly
   name = 'XXX'
   @before
   say(){
      console.log('say')
   }
}

function flag(Constructor){
   Constructor.type = '哺乳类'
}
console.log(Animal.type)
function readonly(target,property,descriptor) {
   setTimeout(() => {
      console.log(target == Animal.prototype)
      console.log(descriptor)
   });
   
}

function before(target,property,descriptor) {
   console.log(descriptor)
}

在这里插入图片描述
可以写一些逻辑代码,例如切片

function before(target,property,descriptor) {
   console.log(descriptor)
   let oldSay = descriptor.value;
   descriptor.value = function () {
      console.log('before')
      oldSay.call(target)
   }
}

let animal = new Animal()
animal.say()

结果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值