转载

前端AOP

野子电竞数据官网改版 https://www.xxe.io/ 全新登场

前端工程化借鉴了很多后端的成功经验,设计模式,MVC,组件化与模块化等,再结合前端本身的分层与分治的特点,逐渐变得复杂。

在angular里ioc,di的概念也开始盛行,而且结合的还不错,不过aop这种说法还真少见,可能是我太孤陋寡闻了吧,不免去百度一下。

一开始听到前端AOP这个提法我还有些吃惊,我是会后端开发的,SPRING的AOP已深入人心,面向切片与切入点都是核心概念,但是javascript做AOP还是真没在项目里做过。js是解释型的语言,语法松散灵活,是一种非强类型的语言,它是一种天生的函数式语言,除了值类型,一些皆为对象,包括函数,前端开发一直以来都是一个页面一个页面地生产的,做AOP的意义何在?而且也没有听说哪个框架里有AOP。后来一查,还真有,在DOJO这个框架里比较流行,不过DOJO我一直没用过,所以就没深入去了解。

所以,我说AOP如果需要用的话,可以用JS闭包来做,在调用其他方法前先调用一个切面方法。现在想想,我觉得这样说也没错,前端模块化基本都是用闭包来实现的,如果不做封装,都是松散的JS文件,何谈AOP?

AOP一般用在哪儿呢?日志记录、权限检查、事务处理,我想权限检查和事务处理最好是放到后端去做,一是为了安全,二是好控制,事务很难在界面逻辑上控制,但在后端的业务逻辑或数据库层就容易的多,而权限检查在前端做就不安全,因为JS和HTML都是文本格式的,代码在前端是暴露的,只能做一些弱检查。日志记录可能是前端AOP主要的一个应用方向吧,但前端代码是在浏览器里运行的,日志记录也很难记到文件里,只能利用cookie或console,前者不适应记录日志,因为会降低性能,而后者主要用来做调试代码用,这么看来,我觉得AOP的作用并不明显,了解一下即可。

使用回调的方式实现AOP:

advice = function(originalFunc){

console.log(“before function”);

originalFunc();

console.log(“after function”);

}

varobj ={

foo: function(){

console.log(‘foo’);

}

}

advice(obj.foo)

1

2

3

4

5

6

7

8

9

10

11

这最简单不过了,要想使用AOP,我们不得不通过advice来调用每一个方法,这种方式的确不够友好。

需要做一些封装,使用闭包来控制:(以下代码来源于网络)

function around(obj, prop, advice){

var exist =obj[prop];

var previous = function(){

return exist.apply(obj, arguments);

};

var advised =advice(previous);

obj[prop] = function(){

//当调用remove后,advised为空

//利用闭包的作用域链中可以访问到advised跟previous变量,根据advised是否为空可以来决定调用谁

return advised ?advised.apply(obj, arguments) : previous.apply(obj, arguments);

};

return{

remove: function(){
    //利用闭包的作用域链,在remove时将advised置空,这样执行过程中不会进入本次around
    //这几个不能删
    //obj[prop] = exist;
    advised = null;
    advice = null;
    //previous = null;
    //exist = null;
    //obj = null;
}

}

1

2

3

4

5

6

7

8

9

10

11

12

}

var count = 1;

advice = function(originalFunc){

var current = count++;

return function() {

console.log("before function " +current);

originalFunc.apply(this, arguments);

console.log("after function " +current);

}

}

var obj ={

foo: function(arg){

console.log(this.name + " and " +arg);

},

name: “obj”

}

h1 = around(obj, ‘foo’, advice);

h2 = around(obj, ‘foo’, advice);

obj.foo(‘hello world’);

//before function 2

//before function 1

//obj and hello world

//after function 1

//after function 2

h1.remove();

obj.foo(‘hello world’);

//before function 2

//obj and hello world

//after function 2

h2.remove();

obj.foo(‘hello world’);

//obj and hello world

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

around前面两个参数指定了对象和对象上的方法,后一个参数指定了切面方法,调用apply的目的是防止this指向脱离obj。

原文  https://segmentfault.com/a/1190000020320125
正文到此结束
Loading...