什么是面向切面编程?
说到面向切面编程,这个一直都是高级工程师必须掌握的一项知识点
生动形象一点的解释就是,写代码就像切面包,如果要你切三刀,最好的保持面包完成度的方法就是;从两头切,而不是一开始就从中间一刀切:
场景一: 统计所有函数谁的耗时最长:
// 常用的方案:
function test(){
var startTime = ....// 业务侵入严重,统计效率低下
alert(2)
var endTime = ....
}
下面是面向切面编程的写法:
fucntion test(){
alert(2);
}
Function.prototype.before = fn=>{
var _self = this;
fn();
_self.apply(this,arguments);
};
Function.prototype.after = fn=>{
var _self = this;
_self.apply(this,arguments);
fn();
};
test.before(function(){
alert(1)
})
test.after(function(){
alert(1)
})
//输出: 1 2 2 3
这样写的好处就是孤立了test方法,回调中申明的任何变量也都不会污染你以前的业务逻辑代码;这就是面向切面编程的优雅之处。
如输出所示,2被输出了两次,这肯定是个bug,所以如下进行优化:
因为默认函数会被执行两次: 解决方案如上所示: 把test作为中转
before回调和before一起送到after去;
同理:假如after写在了前面,自然就是after回调和after一起送到before去
fucntion test(){
alert(2);
}
Function.prototype.before = fn=>{
var _self = this;
return function(){// return回去
// 此时this作为闭包被送到外部: 所以此处的this指向了window对象
fn.apply(_self,arguments);// 此时就保住了this指向
_self.apply(_self,arguments);//此时的this指向还是test Function
}
};
Function.prototype.after = fn=>{
var _self = this;
// 同理改造:
return function(){
_self.apply(_self,arguments);
fn.apply(_self,arguments);
}
};
test.before(function(){
alert(1)
}).after(function(){
alert(3)
})()
//输出 1 2 3
//或者
//test.after(function(){// return function => return 2 3(这一步一开始都是不会执行的)
// alert(3)
//}).before(function(){// 执行 1 fucntion() => 1 2 3
// alert(1)
//})()
//输出 1 2 3
说明:
执行顺序: 执行before中的before回调=>before中的test方法=>执行了after中的回调;
而之所以after的方法中的本身方法会跳过,世界是因为before返回的匿名函数致使this对象发生了改变
拓展: 假如: test方法中有return 的话此时如果按上面的写法, 值就会在挂在的过程中消失:
方案: 你既然执行了人家方法,就要好好将人家送回去:
在after中改造: 因为既然是抛出当然要放在最后
fucntion test(){
alert(2);
return 'colorssk';
}
Function.prototype.before = fn=>{
var _self = this;
return function(){// return回去
if(fn.apply(_self,arguments)== false){
return false
}
return _self.apply(_self,arguments);
}
};
Function.prototype.after = fn=>{
var _self = this;
return function(){
var result = _self.apply(_self,arguments);
if(reslult == false){
return false;
}
fn.apply(_self,arguments);
return result;
}
};
test.after(function(){
alert(3)
}).before(function(){// 执行 1 fucntion() => 2 3
alert(1)
//return fasle//还有一个好处是当此时抛出异常的时候只需要return false就会停止接下来的链式操作
})()
输出 1 2 3
colorssk
以上是面向切面编程的一种思想,这种解耦的思想,也是抽象思维的一种表现,当埋点或者临时插入业务逻辑代码的时候,可以方便于后期的维护