定义

在不改变原对象的基础上,通过对其进行包装扩展(添加属性和方法)使原有对象可以满足用户更复杂的需求

demo

缓存函数引用

  1. let decorator = function (input,type) {
  2. let inp = document.getElementById(input);
  3. let click;
  4. if(Object.prototype.toString.call(inp.onclick) === '[object Function]'){
  5. // 缓存原有事件
  6. click = inp.onclick;
  7. }
  8. inp.onclick = function () {
  9. // 事件原有函数
  10. click && click();
  11. fn();
  12. }
  13. };

缺点

要维护额外的中间变量(_foo),如果装饰链过长,中间变量就会越来越多

可能会存在this被劫持问题

  1. var getId = document.getElementById;
  2. document.getElementById = function(ID){
  3. console.log(1);
  4. return getId(ID);
  5. }
  6. document.getElementById('demo');

修改:

  1. var getId = document.getElementById;
  2. document.getElementById = function(ID){
  3. console.log(1);
  4. return getId.call(document, ID);
  5. }
  6. document.getElementById('demo');

AOP装饰函数

前置装饰

  1. Function.prototype.before = function(beforeFunc){
  2. var that = this;
  3. return function(){
  4. beforeFunc.apply(this, arguments);
  5. return that.apply(this, arguments);
  6. }
  7. }

后置装饰

  1. Function.prototype.after = function(afterFunc){
  2. var that = this;
  3. return function(){
  4. var ret = that.apply(this, arguments);
  5. afterFunc.apply(this, arguments);
  6. return ret;
  7. }
  8. }

总结

1、装饰者和被装饰者对象有相同的超类型,所以在任何需要原始对象(被装饰者)的场合,都可以用装饰过得对象代替原始对象。
2、可以用一个或多个装饰者包装一个对象(被装饰者)
3、装饰者可以在所委托的装饰者行为之前或之后加上自己的行为,以达到特定的目的
4、被装饰者可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
5、装饰者会导致出现很多小对象,如果过度使用,会让程序变得复杂。