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") );