开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情
Angular中大量使用了装饰器,有Component装饰器,Module装饰器,有Input装饰器,方法装饰器,属性装饰器等。而且还可以自定义装饰器。本系列文章会和大家一起来感受装饰器的美。
装饰器
修饰器是ES7加入的新特性,修饰器实际上就是设计模式中常说的装饰者模式的一种实现。在ES6开始,设计模式原生化就已经是非常明显的趋势了,无论是for..of.. 和Iterator接口的配合内化了迭代者模式,Proxy对象实现的代理模式等等,都可以看出Javascript逐渐走向标准化的趋势和决心。
装饰器模式
装饰器模式(Decorator Pattern),是指在不必改变原类文件或使用继承的情况下,动态地扩展一个对象的功能,为对象增加额外特性的一种设计模式。它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
装饰器就是为了解决在不修改原本组件、接口或者类的时候为其添加额外的功能。
- 从本质上看,装饰器模式是一个包装模式((Wrapper Pattern),它是通过封装其他对象达到设计的目的;
- 从结果的角度来看,使用装饰器和直接修改类的定义没有什么区别,但使用装饰器更符合开放封闭原则,且更符合声明式的思想;
由于ES7中已经可以使用装饰器了,我们先慢慢来哈,先来了解一下ES7中的装饰器。
ES7的装饰器
装饰器目前还处于草稿阶段,不过可以先来了解一下。
装饰器可以装饰四种类型的值:
- 类;
- 类的属性;
- 类的方法;
- 属性存取器;
class装饰器
装饰器的本质是一种函数,写成 @ + 函数名。
@addSkill
class Person { }
function addSkill(target) {
target.say = "hello world"; //直接添加到类中
target.prototype.eat = "apple"; //添加到类的原型对象中
}
var personOne = new Person();
console.log(Person['say']); // 'hello world'
console.log(personOne['eat']); // 'apple'
如果在class上添加一个装饰器,发现在浏览器中是无法直接运行的,浏览器对于这种语法糖还不支持。如果要想使用它,还需要提前做一些准备工作,对它进行编译。
- 安装插件;
npm i babel-plugin-transform-decorators-legacy babel-register --save-dev
- 创建compile.js文件
const babel = require('babel-register');
babel({
plugins: ['transform-decorators-legacy']
});
require('./app.js');
- app文件
@addSkill
class Person { }
function addSkill(target) {
target.say = "hello world"; //直接添加到类中
target.prototype.eat = "apple"; //添加到类的原型对象中
}
var personOne = new Person();
console.log(Person['say']); // 'hello world'
console.log(personOne['eat']); // 'apple'
- 执行compile.js
装饰器还可以带参数:
@addSkill('I love')
class Person { }
function addSkill(msg) {
return function(target){
target.prototype.eat = msg + ' ' + "apple";
}
}
var personOne = new Person();
console.log(personOne.eat);
上面的例子中,由于装饰器要携带参数,addSkill('I love')必须返回一个函数,所以,addSkill就是一个函数的函数。
本文,我们先从整体上介绍了解了什么是装饰器,以及装饰器模式,和ES7中Class装饰器。后续文章,会继续分享这一部分哦。