小姜哥的微信

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);
// 以下是测试代码:
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(&quot;url&quot;)  );</pre>

==== 2013.04.12 update

本程序已经略做修改并提交github(https://github.com/notejs/aop),现在可同时支持浏览器和node.js环境。

浏览器环境可以通过window.aop使用。

node.js环境安装方法为npm install node-aop。

推荐文章

回到顶部