给AOP的after函数使用原函数局部变量
引:AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
这里我们可以理解为在执行某函数时,要先执行什么,或最后执行什么。
比如:
function a() { alert(1) } function b() { alert(2) } //如果要先打印1再打印2 a(); b(); //又或者把a()改为 function a(){ alert(1); b(); }
第一种方法显得累赘,而且在改造升级的情况下,可能会使function b()没了,然后会报错,第二种方法代码入侵性太大。
我们可以使用AOP去改善这种逻辑。
关于实现和应用场景大家可以参考alloyteam,这文章(http://www.alloyteam.com/2013/08/yong-aop-gai-shan-javascript-dai-ma/)
现在这里讨论的是after函数如何使用原函数的局部变量。
就拿alloyteam代码做个例子。
AOP实现:
Function.prototype.before = function (func) { var __self = this; return function () { if (func.apply(this, arguments) === false) { return false; } return __self.apply(this, arguments); } } Function.prototype.after = function (func) { var __self = this; return function(){ var ret = __self.apply(this, arguments); if (ret === false) { return false; } func.apply(this, arguments); return ret; } }
那么刚才的例子可以写成这样:
var a = a.after(b); a();
现在想要函数b可以用到函数a里面的一个变量,就要使函数a最后return 返回变量。
如果我们不想改变函数a,又或者函数a的第三方代码,那怎么办,改动起来无疑麻烦,这里我新建一个方法insertAfter,
虽然这个改造有入侵性,但我们可以选择性使用这个方法。
Function.prototype.insertAfter = function (func) { var oldFuncStr = this.toString(); var aftFuncStr = func.toString(); oldFuncStr = oldFuncStr.replace(/^function(.*){/, ''); var newFuncStr = oldFuncStr.replace(/}$/, '~'+aftFuncStr+'()'); var newFunc = new Function ("", newFuncStr); return newFunc; }
这样,after进去的函数就可以使用原函数的局部变量了。
注意原函数有return的情况,就应该把after内容放在return前面,如果是return false,可以忽略了。这里只给出思路。希望读者可以自行改造。
下面给出完整例子:
Function.prototype.insertAfter = function (func) { var oldFuncStr = this.toString(); var aftFuncStr = func.toString(); oldFuncStr = oldFuncStr.replace(/^function(.*){/, ''); var newFuncStr = oldFuncStr.replace(/}$/, '~'+aftFuncStr+'()'); var newFunc = new Function ("", newFuncStr); return newFunc; } //Usage function a(){ var x = 123; alert(1); } function b(){ alert(x); } var a = a.insertAfter(b); a();