最近从朋友那边白嫖了一只猫,说起这个撸猫,真是不得了,太有瘾了,撸起来就停不下来,这可爱的小家伙喵喵喵的,甄氏萌翻了。早上喂了早饭,铲了屎就去上班了。
中午 12:00,我开始躁动不安了,我家猫咋样了,是不是饿着了,是不是渴了。有没有拆我家电视,有没有挠我的沙发,不行了,awsl,我要知道我家猫在干啥。
- 我想知道我家猫在干啥
- 我不想打扰我家猫正常的生活
这不就是 AOP 嘛,刚好最近正好工作有用到了 AOP,那我们不得不说一下什么是 AOP?
Aspect-oriented programming
面向切面编程,旨在通过允许跨领域关注点的分离来提高模块化。通常呢是通过不修改代码本身的情况下向现有代码添加其他行为,目标是一个切入点,切面,所以也就有了面向切面编程这个说法。值得一提的是,AOP 是一种编程规范,并不是一种纯粹的技术,她只提供了定义,具体实现还是有很多种的,比较常见的就是装饰器的形式。
function business() {
console.log('I will do some business!');
}
async function asyncBusiness() {
await new Promise(resolve => setTimeout(() => resolve('ohhhhhhhhhh'), 3000));
console.log('I will do some async business!');
}
function monitor(callback) {
return async function() {
console.log('monitor start');
const result = await callback.apply(this, arguments);
console.log('monitor end');
return result;
};
}
const monitorBusiness = monitor(business);
const monitorAsyncBusiness = monitor(asyncBusiness);
business();
monitorBusiness();
await asyncBusiness();
await monitorAsyncBusiness();
其实一个装饰器就是这么简单,那么我们常见的@的形式来实现的装饰器是什么样的呢?@形式的装饰器其实是利用了 Object.defineProperty。
Object.defineProperty
Object.defineProperty(obj, prop, descriptor)
obj
The object on which to define the property.prop
The name or Symbol of the property to be defined or modified.descriptor
The descriptor for the property being defined or modified.
详细的内容不在本期讲解,如果有兴趣,请关注我们的公众号 ihap 技术黑洞 ,之后我才会告诉你在 MDN 的链接是
不关注的你们就不知道了!
decorator
回到我们的装饰器上,那么怎么写一个在类里可以使用的装饰器呢?
ok, 逼格 than 逼格,让我们优雅的在代码里逼格一下!
class WatchCat {
@log
eat() {
console.log('cat is eatting');
}
@log
drink() {
console.log('cat is drink');
}
}
function log(target) {
if (target.kind === 'method') {
const original = target.descriptor.value;
target.descriptor = {
...target.descriptor,
async value(...args) {
try {
console.log('I am watching my cat!');
const result = await original.apply(this, args);
console.log('I am finished watch my cat!');
return result;
} catch (err) {
console.error('sorry, my cat broken my monitor');
throw err;
}
},
};
}
return target;
}
const watchCat = new WatchCat();
watchCat.eat();
这样,在我们对猫进行观察的时候,猫并没有产生什么反应,还是在吃饭。
好了,我决定买个摄像头来监视我的猫每天究竟在干嘛
实际上它每天我不在的时候就在吃睡,怪不得每天晚上都是这么精神。
好了,本次的肥少带你撸猫之旅就到此结束了。不说了,问问客服能不能退货,摄像头完全没有意义了。
自此感谢我们 ihap 技术黑洞 的镇号之宠——芝麻!友情出演。
你们是不是以为没了?哈哈哈哈哈哈哈,突然想起来忘记给你们讲@log('ihap 技术黑洞')如果有参数的形式,要怎么写了。
function log(name) {
return target => {
if (target.kind === 'method') {
const original = target.descriptor.value;
target.descriptor = {
...target.descriptor,
async value(...args) {
try {
console.log(`${name} is watching my cat!`);
const result = await original.apply(this, args);
console.log(`${name} is finished watch my cat!`);
return result;
} catch (err) {
console.error('sorry, my cat broken my monitor');
throw err;
}
},
};
}
return target;
};
}
好了,真的没有了,大家白白!
参考文献:
https://stackoverflow.com/questions/8112111/is-aop-a-type-of-decorator-pattern
https://www.sitepoint.com/javascript-decorators-what-they-are/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty