理解前端设计模式(三)

135 阅读2分钟

装饰者模式

在不改变对象的基础上,在程序运行期间给对象动态地增加职责

比如天冷了就多穿件外套~

从结构上看更适合称为包装器(wrapper)模式。装饰者模式将一个对象嵌入另一个对象之中,实际上相当于这个对象被另一个对象包装起来,形成一条包装链。请求随着这条链依次传递到所有的对象,每个对象都有处理这条请求的机会

b要改变对象可以直接修改属性,而要改变函数在不碰原函数的前提下,就只能把它在另一个函数里引用,如下

var a = function(){
 alert (1);
}
var _a = a;
a = function(){
 _a();
 alert (2);
}
a(); 

这样的写法有两个问题

  • 每次需要改变函数都要多维护一个变量
  • 原函数可能是一个对象的方法,但_a是window的属性,调用时会有this指向问题 接下来看下在职责链模式中提到的AOP,实现一个完美的装饰器
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;
 }
}; 

唯一的不足是这个方法会污染原型,那我们可以换个方式,将原函数也作为参数

var before = function( fn, beforefn ){
 return function(){
 beforefn.apply( this, arguments );
 return fn.apply( this, arguments );
 }
}
var a = before(
 function(){alert (3)},
 function(){alert (2)}
);
a = before( a, function(){alert (1);} );
a();