原文 :http://blog.csdn.net/notejs/article/details/8770575
面向切面的编程(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("url") );
==== 2013.04.12 update
本程序已经略做修改并提交github(https://github.com/notejs/aop),现在可同时支持浏览器和node.js环境。
浏览器环境可以通过window.aop使用。
node.js环境安装方法为npm install node-aop。