ES7中的decorator

本文介绍了ES7中的装饰器(decorator)概念及其用法,包括装饰类和类的属性。并通过实例展示了如何利用装饰器实现类的扩展,如添加只读属性和日志记录等功能。

ES7中的decorator

什么是decorator

decorator,顾名思义,装饰器,用来装饰类或者类的方法,目前在ECMAScript中已经有提案加入了这个功能。 decorator主要的作用就是可以用来修改类或者方法的默认行为,增加一些自定义操作,并且不会影响原有的逻辑,如常用的安全检查,日志系统,调试功能等。

如何使用decorator

decorator的使用方法有两种,一种是给类添加decorator,另一种是给类的属性添加decorator(普通的对象字面量属性也可以添加装饰器)。(注意decorator不能用于装饰函数,因为函数存在函数提升的情况) 先来看第一种情况。

const decorator = (target) => {
  target.isAnimal = true;
};

@decorator
class Cat {

}
console.log(Cat.isAnimal); // true

在上面的例子中,我们为Cat类增加了名为decorator的装饰器,意味着我们需要装饰的是这个类,在decorator方法中的参数target指的就是要装饰的类,在例子中是Cat类。为Cat类增加了一个属性 isAnimal,则我们的Cat上就会挂载一个isAnimal属性,我们并不需要去修改原有的Cat类,即可修改Cat的默认行为。

接下来再看一个例子,我们想给一个Fruit类增加同样的装饰器。

const decorator = (target) => {
  target.isAnimal = true;
};

@decorator
class Fruit {

}
console.log(Fruit.isAnimal); // true

很明显,水果并不是动物,那么我们能不能使用装饰器的同时去做一些限制或者说增加一些条件的设定呢?答案是可以的。

const decorator = (flag) => (target) => {
  target.isAnimal = flag;
};

@decorator(false)
class Fruit {

}

@decorator(true)
class Cat {

}

console.log(Fruit.isAnimal); // false
console.log(Cat.isAnimal); // true

在上面的示例中,我们为装饰器增加了参数,完善了装饰器的功能。通过设定参数,可以更好的控制被装饰类。

接下来看第二种情况,给类的属性增加装饰器

写一个比较常见的情况,限制类的属性让其变为只读

const readonly = (target, key, descriptor) => {
  descriptor.writable = false;
  return descriptor;
};

class Cat {
  @readonly
  age = 4;
}

var cat = new Cat();
cat.age = 5;
console.log(cat.age);  // Uncaught TypeError: Cannot assign to read only property 'age' of object '#<Cat>'

现在,age属性变为只读属性了,对于age的修改操作都会在控制台提示报错。

同理,如果我们想通过参数去控制此属性是否需要设置成只读呢?同样的,写法类似于上面第一种情况的示例。

const readonly = (flag) => (target, key, descriptor) => {
  descriptor.writable = !flag;
  return descriptor;
};

class Cat {
  @readonly(false)
  age = 4;
  @readonly(true)
  name = 'tom';
}

var cat = new Cat();
cat.age = 5;
cat.name = 'jack';
console.log(cat.age); // 5
console.log(cat.name);// Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Cat>'

我们注意到,第二种情况和第一种情况的写法不太一样,多了两个参数,如果仔细看的话,会发现,是不是和Object.defineProperty的参数很像?或者说是一模一样。

实际上它的执行就是

descriptor = readonly(Cat.prototype, 'age', descriptor) || descriptor

通过重新定义对象的属性,包装一个新的属性描述符安装到对应属性上来达到装饰原有属性的行为。

至此,decorator的两种使用方法,都做了介绍。

decorator的应用场景

说了什么是decorator以及怎么写一个decorator之后,接下来要说的就是decorator的应用场景了。一个比较常见的场景是,一个记录操作的日志系统。

这里我们写一个数码宝贝中亚古兽的进化过程。

class Agumon {
  name = '亚古兽';
  startEvolution(name) {
    this.name = name;
  }

  currentName() {
    console.log(this.name);;
  }
}

var agumon = new Agumon();
agumon.currentName(); // 亚古兽

agumon.startEvolution('暴龙兽');
agumon.currentName(); // 暴龙兽

agumon.startEvolution('战斗暴龙兽');
agumon.currentName(); // 战斗暴龙兽

如果我们想记录亚古兽的每次进化,则可以写一个日志系统来记录亚古兽的每次进化。

const evolutionLog = (target, name, descriptor) => {
  const oldName = descriptor.value;
  descriptor.value = function(...arg) {
    console.log(`进化:  ${arg}`);
    return oldName.apply(this, arg);
  }
};

class Agumon {
  name = '亚古兽';

  @evolutionLog
  startEvolution(name) {
    this.name = name;
  }

  currentName() {
    console.log(this.name);
  }
}

var agumon = new Agumon();
agumon.currentName();

agumon.startEvolution('暴龙兽');
agumon.currentName();

agumon.startEvolution('战斗暴龙兽');
agumon.currentName();

// 亚古兽
// 进化:  暴龙兽
// 暴龙兽
// 进化:  战斗暴龙兽
// 战斗暴龙兽

详情关注博客 https://mmmaming.github.io/

《基于Spring Boot的旅游路线规划系统》是一个旨在帮助旅行者规划旅游路线、提供旅游景点信息和优化旅行体验的创新项目。该系统采用了现代化的Spring Boot后端框架,致力于为用户提供一个集中管理旅游景点、规划旅游路线和提供相关信息的综合平台。该系统的主要目标是为旅行者提供全面的旅游路线规划功能。用户可以通过系统浏览各个旅游景点的详细信息,包括景点介绍、开放时间和交通方式等。系统支持用户规划旅游路线,根据用户的偏好和时间限制,推荐最佳的路线选择。用户可以根据系统提供的路线推荐进行调整,并查看每个景点之间的交通信息和推荐行程。除了旅游路线规划功能,该系统还提供了旅游景点信息和用户评价功能。系统收集了各个旅游景点的详细信息,并提供实时更新的开放时间和交通信息。用户可以查看其他旅行者对景点的评价和意见,帮助他们做出更好的决策。用户还可以自己对景点进行评价和评论,与其他用户分享旅游经验。该系统注重用户体验和界面设计。通过使用Spring Boot框架,系统具有快速响应和稳定性能。同时,系统采用直观的界面设计,提供良好的用户体验。系统还支持多设备访问,用户可以在不同的设备上方便地访问和使用系统。总之,基于Spring Boot的旅游路线规划系统是一个为旅行者提供旅游路线规划、景点信息和优化旅行体验的综合平台。通过该系统,用户可以浏览旅游景点的详细信息,规划个性化的旅游路线,并获得相关的交通信息和推荐行程。系统的景点评价和用户互动功能帮助用户获取更多的旅游信息和分享旅行经验。无论是自由行旅行者还是旅游规划师,都能从该系统中获得便捷、个性化和优化的旅行路线规划体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值