js实现面向切面的编程(AOP)

js实现面向切面的编程(AOP)

面向切面的编程(AOP) 还是有点意思的,可以在不修改原有代码的情况下增加新功能。有一些js框架实现AOP功能,但是有些时候我们并不能依赖于框架写程序(框架可能很笨重), 我们需要自己实现一些适合我们的功能模块。下面是我自己实现的js AOP,实现了before和after功能,仅供抛砖。

如下是aspect.js,是实现AOP的全过程。


(function(window, undefined){
 function aspect(type){
  return function(target, methodName, advice){
   var exist = target[methodName],
    dispatcher;

   if( !exist || exist.target != target ){
    dispatcher = target[methodName] =  function(){
     // before methods
     var beforeArr = dispatcher.before;
     var args = arguments;
     for(var l = beforeArr.length ; l--; ){
      args = beforeArr[l].advice.apply(this, args) || args;
     }
     // target method
     var rs = dispatcher.method.apply(this, args);
     // after methods
     var afterArr = dispatcher.after;
     for(var i = 0, ii = afterArr.length; i < ii; i++){
      rs = afterArr[i].advice.call(this, rs, args) || rs;
     }
     // return object
     return rs;
    }

    dispatcher.before = [];
    dispatcher.after = [];

    if( exist ){
     dispatcher.method = exist;
    }
    dispatcher.target = target;
   }

   var aspectArr = (dispatcher || exist)[type];
   var obj = {
    advice : advice,
    _index : aspectArr.length,
    remove : function(){
     aspectArr.splice(this._index, 1);
    }
   };
   aspectArr.push(obj);

   return obj;
  };
 }

 window.aspect = {
  before : aspect("before"),
  after : aspect("after")
 };

 return window.aspect;

})(window, undefined);
以下是测试代码:

 var as = window.aspect;

 var obj = {
  url:"",
  get : function(key){
   return this["key"];
  },
  set : function(key, value){
   this["key"] = value;
  }
 };

 var h1 = as.before(obj, "set", function(key, value){
  // 返回一个数组可以修改参数
  value += " before-1 ";
  //console.log(value);
  return [key, value];
 });

 var h2 = as.before(obj, "set", function(key, value){
  // 没有返回值则参数不会变化
  value += " before-2 ";
  //console.log(value);
 });

 obj.set("url", "http://mojijs.com");
 console.log( obj.get("url") );

 var h3 = as.after(obj, "get", function(value){
  // 没有返回值不会修改原函数的返回值
  value += " after-1 ";
  //console.log(value);
 });

 var h4 = as.after(obj, "get", function(value){
  // 有返回值会修改原函数的返回值
  value += " after-2 ";
  //console.log(value);
  return value;
 });

 console.log( obj.get("url") );

 h1.remove(); // 删除切面方法
 h4.remove(); // 删除切面方法

 obj.set("url", "http://baidu.com");
 console.log( obj.get("url") );

posted on 2014-08-25 10:18  山冈龙  阅读(1176)  评论(0编辑  收藏  举报

导航