最近碰到一个需求,有那么一组方法和一个检查机制,只有检查结果通过时才执行对应的代码,否则直接提示,不执行代码。最简单的办法当然是在每个方法执行前加if判断,但是那样的话代码冗余,而且代码看上去实在很愚。
初次尝试
本想使用IIFE遍历对象,针对特定方法添加判断,这样一来就不存在冗余问题。使用的是Angular的factory服务模块。
return (function (instance) {
for (var name in instance) {
var method = instance[name];
if (typeof method === 'function')) {
instance[name] = function (name, method) {
return function () {
if (check()) {
return method.apply(this, arguments);
} else {
// 提示不通过
}
}
}(name, method);
}
}
return instance;
})({
funA: funA,
funB:funB
});
我一开始看上去觉得没问题的样子,可是忘记考虑到Angular的service是单例模式,这样一来,如果在第一次注入服务的时候,初始化完成时检查就是不通过的或者是通过的,那么就一直是这种状态,有点像惰性函数了,这样一来就存在问题。
AOP
有没有可能通过AOP解决问题呢,毕竟两者的使用场景有点类似,不过AOP关注点在执行顺序上,为业务代码添加额外的功能,在业务之前或之后执行,将和业务无光的代码抽离出来。不管啦,看看JavaScript如何实现AOP呢?简单代码如下:
Function.prototype.before=function(beforefn){
var __self=this;
return function(){
beforefn.apply(this,arguments);
return __self.apply(this,arguments);
}
}
Function.prototype.after=function(afterfn){
var __self=this;
return function(){
var ret=__self.apply(this,arguments);
afterfn.apply(this,arguments);
return ret;
}
}
看了这段代码真是恍然大悟,之前一直考虑如何得到方法对象,却没有想到方法也是对象,所有方法都是Function的实例,那么我们可以在Function原型链上扩充方法,这样一来我们声明的方法就会具备这个方法,调用的时候便可以通过this得到方法。有没有很酷!
AOP修改
了解了AOP的原理之后,我们稍加修改便可以达到自己的需求,需要注意的时,我们的检查机制在每次执行都需要检查,而不是只检查一次,因此如下的代码会有问题,虽然通用性强!
Function.prototype.before = function(check) {
var __self = this;
return function() {
if(check.apply(this,arguments)){
return __self.apply(this, arguments);
}else{
// 提示不通过
}
}
}
return {
funA: funA,
funB: funA.before(check),
}
怎么办,那就只能和业务结合起来了。代码如下:
Function.prototype.before = function() {
var __self = this;
return function() {
if(check()){
return __self.apply(this, arguments);
}else{
// 提示不通过
}
}
}
return {
funA: funA,
funB: funA.before(),
}
可能存在的问题
- 直接在Function原型链上扩展,后期会不会被覆盖呢?
- 使用apply执行方法和()执行的区别?
- 显示绑定上下文
- arguments是一个ArrayLike,直接传递给方法执行表达式会报错