JavaScript设计模式(12)—— 装饰器模式
程序员文章站
2022-07-02 19:20:50
装饰器模式的定义装饰器模式=表面意思,当用户发出相同的请求,如调用一个名为work()的函数,有些人的作息是955,而被装饰之后,就变成996了。用代码复现一下上面的场景如下所示:let work = function(){ console.log('work:9:00 - 17:00') } let _work = work work = function(){ _work() console.log('work:17:00 - 21:00') } work()...
装饰器模式的定义
装饰器模式=表面意思,当用户发出相同的请求,如调用一个名为work()的函数,有些人的作息是955,而被装饰之后,就变成996了。用代码复现一下上面的场景如下所示:
let work = function(){
console.log('work:9:00 - 17:00')
}
let _work = work
work = function(){
_work()
console.log('work:17:00 - 21:00')
}
work()
相同的请求获得不同的结果,这跟第三章的代理模式有些相似,但装饰器模式更加强调往原有的请求里面加点料,而代理模式则常用来判断请求该被如何处理。
装饰器模式的危害
从上面的简易代码中可以得出如下信息,装饰器模式不修改请求的名称,但悄咪咪往请求里加了点料。在原著中,作者通过许多例子介绍了装饰器模式的实用性,而我从其中一个例子里悟到了装饰器模式的危害,因为这个例子是我切身体会到的,分享给各位希望各位在使用装饰器模式的时候注意一个非常非常重要的点:注释!
在我第一次在X公司实习的时候,接触到的第一个项目就是一个转手的项目,项目本身不重要,有一天我遇到一个“bug”。说用户点击了某个按钮之后出现了一条报错信息。ok,那时候我接触的还是原生+jq。下面开始排查错误
- 第一步 找到用户说的那个按钮,查到id=‘abc’, 然后我在代码里找到如下代码
document.getByElementId('abc').onclick = function(){ test() }
- 确认了test函数有问题之后,我立马定位到test()函数开始排查错误
- 查了半天我没有搞懂那条报错信息是怎么出来的
- 最后发现,页面初始化的时候这个test()函数被装饰器模式重写过,卜但执行了test()还执行了另一个函数,我查NMD
因此在使用装饰器模式的时候,请务必在原函数的旁边注释一下这个函数在哪里被装饰过,不然哪一天装饰的代码报错了你搁那疯狂排查原函数的错误,像个哈皮。
用AOP装饰函数
由于work的写法过于简陋,使得代码看起来不是很高大上,同时上面的写法还存在this指向被劫持的问题,因此在这里提供一种通用的方法将装饰器模式封装一下,通常装饰器模式会在函数执行前或执行后执行装饰属性,因此我们提供Function.prototype.before 方法和 Function.prototype.after方法来解决这两种情况。
Function.prototype.before = function( beforefn ){
var __self = this; // 保存原函数的引用
return function(){ // 返回包含了原函数和新函数的"代理"函数
beforefn.apply( this, arguments ); // 执行新函数,且保证 this 不被劫持,新函数接受的参数
// 也会被原封不动地传入原函数,新函数在原函数之前执行
return __self.apply( this, arguments ); // 执行原函数并返回原函数的执行结果,
// 并且保证 this 不被劫持
}
}
Function.prototype.after = function( afterfn ){
var __self = this;
return function(){
var ret = __self.apply( this, arguments );
afterfn.apply( this, arguments );
return ret;
}
};
work.after(function(){
console.log('work:17:00 - 21:00')
})
本文地址:https://blog.csdn.net/dkr380205984/article/details/112830258