详解如何在JavaScript中使用装饰器

 更新时间:2022年10月25日 15:36:08   作者:前端lucio  
Decorator装饰器是ES7的时候提案的特性,目前处于Stage 3候选阶段(2022年10月)。装饰器简单来说就是修改类和类方法的语法糖,很多面向对象语言都有装饰器这一特性。本文就来说说如何在JavaScript中使用装饰器,需要的可以参考一下

Decorator装饰器是ES7的时候提案的特性,目前处于Stage 3候选阶段(2022年10月)。

装饰器简单来说就是修改类和类方法的语法糖,很多面向对象语言都有装饰器这一特性。

为了使用装饰器特性,我们需要用进行babel转义。这里需要用到的是@babel/plugin-proposal-decorators

安装

npm install --save-dev @babel/plugin-proposal-decorators

vite配置

import { defineConfig } from 'vite';
import babel from 'vite-plugin-babel';

export default defineConfig({
    plugins: [
        babelDev({
            babelConfig: {
                plugin: ['@babel/plugin-proposal-decorators']
            }
        }),
        // ...
    ],

    // ...
})

webpack配置

module: {
  rules: [
    {
      test: /\.(js|mjs|jsx|ts|tsx)$/,
      use: {
        loader: 'babel-loader',
        options: {
          // ... 
          plugins: [
            ['@babel/plugin-proposal-decorators', { 'legacy': true }],
            // ...
          ],
          // ...
        },
      }
      // ...
    }
  ]
}  

使用

先来一图了解装饰器语法。

语法: @+函数名

@frozen
class Foo {
  @throttle(500)
  expensiveMethod() {}
}

类装饰器

参数target是类本身

function testable(target) {
  target.isTestable = true;
}

@testable
class MyTestableClass {
  // ...
}
MyTestableClass.isTestable // true

带参数的修饰器

@+返回装饰器函数的表达式

function testable(isTestable) {
  return function(target) {
    target.isTestable = isTestable;
  }
}
@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true
@testable(false)
class MyClass {}
MyClass.isTestable // false

类成员装饰器

参数:

  • target:被修饰的类的原型对象
  • name:类成员的名字
  • descriptor:类成员的描述对象
function readonly(target, name, descriptor){
  // descriptor对象原来的值如下
  // {
  //   value: specifiedFunction,
  //   enumerable: false,
  //   configurable: true,
  //   writable: true
  // };
  descriptor.writable = false;
  return descriptor;
}

class Person {
  @readonly
  name() { return `${this.first} ${this.last}` }
}

多个装饰器的执行顺序

洋葱模型,先从外到内进入,然后由内向外执行

function dec(id){
  console.log('evaluated', id);
  return (target, property, descriptor) => console.log('executed', id);
}
class Example {
    @dec(1)
    @dec(2)
    method(){}
}
// evaluated 1
// evaluated 2
// executed 2
// executed 1

应用

延迟

class Page {
	@delay(2000)
	onClick(a) {
    console.log("onClick");
  }
}
function delay(time) {
  return function (target, key, descriptor) {
    const oldFunction = descriptor.value;
    descriptor.value = function() {
      setTimeout(() => {
        oldFunction.apply(this, arguments);
      }, time);
    }
    return descriptor;
  }
}

节流

如果在定时器的时间范围内再次触发,则不予理睬,等当前定时器完成,才能启动下一个定时器任务

class Page {
	@throttle(2000)
	onClick(a) {
    console.log("onClick");
  }
}
function throttle(time) {
  return function (target, key, descriptor) {
    const oldFunction = descriptor.value;
    let isLock = false;
    descriptor.value = function() {
      if(isLock) { return; }
     	isLock = true;
      oldFunction.apply(this, arguments);
      setTimeout(() => {
        isLock = false; 
      }, time);
    }
    return descriptor;
  }
}

防抖

每次事件触发则删除原来的定时器,建立新的定时器。

class Page {
	@debounce(2000)
	onClick(a) {
    console.log("onClick");
  }
}
function debounce(time) {
  return function (target, key, descriptor) {
    const oldFunction = descriptor.value;
    let timer = null;
    descriptor.value = function () {
      clearTimeout(timer);
      timer = setTimeout(() => {
        oldFunction.apply(this, arguments)
      }, time);
    };
    return descriptor;
  }
}

到此这篇关于详解如何在JavaScript中使用装饰器的文章就介绍到这了,更多相关JavaScript使用装饰器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JS解决回调地狱为什么需要Promise来优化异步编程

    JS解决回调地狱为什么需要Promise来优化异步编程

    这篇文章主要为大家介绍了JS解决回调地狱为什么需要Promise来优化异步编程原理解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • JavaScript中的事件处理程序

    JavaScript中的事件处理程序

    这篇文章介绍了JavaScript中的事件处理程序,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • js报错 Object doesn''t support this property or method的原因分析

    js报错 Object doesn''t support this property or method的原因分析

    运行js是出现Object doesn't support this property or method 错误的可能原因分析。
    2011-03-03
  • 教您去掉ie网页加载进度条的方法

    教您去掉ie网页加载进度条的方法

    相信很多同仁做的系统后到都是用frameset或iframe来加载不同页面的,不可不知道大家有没有注意到,当frame框架中的页面已经加载完成后,可是ie浏览器的状态栏还会一直显示一个正在加载的状态。
    2010-12-12
  • 带你使用webpack快速构建web项目的方法

    带你使用webpack快速构建web项目的方法

    这篇文章主要介绍了带你使用webpack快速构建web项目的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 详细聊聊对async/await的理解和用法

    详细聊聊对async/await的理解和用法

    随着Nodev7的发布,越来越多的人开始研究据说是异步编程终级解决方案的 async/await,这篇文章主要给大家介绍了关于对async/await的理解和用法,文中通过实例代码介绍的介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • 详解javascript replace高级用法

    详解javascript replace高级用法

    这篇文章主要介绍了详解javascript replace高级用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-02-02
  • JS前端框架关于重构的失败经验分享

    JS前端框架关于重构的失败经验分享

    关于重构JS前端框架的失败经验接下来与大家分享一下,感兴趣的你可不要错过了哈,毕竟是经验之谈哈
    2013-03-03
  • Summernote实现图片上传功能的简单方法

    Summernote实现图片上传功能的简单方法

    下面小编就为大家带来一篇Summernote实现图片上传功能的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07

最新评论