felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

JavaScript 的面向切面编程 #135

Open felix-cao opened 5 years ago

felix-cao commented 5 years ago

一、什么是面向切面编程

面向切面编程,英文叫 Aspect Oriented Programming,简称 AOP。面向切面编程是把与核心业务逻辑无关的功能抽离出来,再通过“动态织入”的方式掺入业务逻辑模块中。这些跟业务逻辑无关的功能通常包括日志统计、安全控制、异常处理等。把这些功能抽离出来之后,

二、AOP 能给我们带来什么好处?

AOP 的好处首先是可以保持业务逻辑模块的纯净和高内聚性,其次是可以很方便地复用日志统计等功能模块。

三、JavaScript 之 AOP 的实现

Java 语言中,可以通过反射和动态代理机制来实现 AOP 技术,而在 JavaScript 这种动态语言中,AOP 的实现很简单,这是 JavaScript 天生神力!

AOP 中,通知 是切面的具体实现,分为 before(前置通知)、after(后置通知)、around(环绕通知),下面通过扩展 Function.prototype 来做 AOP

Function.prototype.before = function( beforeFn ) { 
  var that = this; // 保存原函数的引用 
  return function() { // 返回包含了原函数和新函数的"代理"函数, 代号 code1 
    beforeFn.apply( this, arguments ); // beforeFn函数作为参数传递进来的,修正 this 
    that.apply( this, arguments ); // 保存的函数放在这里
} };

Function.prototype.after = function( afterFn ) { 
  var that= this; // 保存
  return function() { // 再次返回一个新函数
    that.apply( this, arguments ); // 保存的函数放在这里
    afterFn.apply( this, arguments ); // afterFn函数作为参数传递进来
} };

var fun = function() { 
  console.log( 2 ); 
};

var fn = fun.before(function() { 
  console.log( 1 ); 
}).after(function() {
  console.log( 3 );
});

fn();

我们把负责打印数字 1 和打印数字 3 的两个函数通过 AOP 的方式动态植入 fun 函数。通过执行上面的代码,我们看到控制台顺利地返回了执行结果 1、2、3。

这种使用 AOP 的方式来给函数添加职责,也是 JavaScript 语言中一种非常特别和巧妙的装饰 者模式实现。这种装饰者模式在实际开发中非常有用。

around(环绕通知)

function around(obj, prop, advice){
 var exist = obj[prop];
 var advised = advice(function(){
  return exist.call(obj, arguments);
 });
 obj[prop] = advised;
}

advice = function(originalFunc){
 return function() {
  console.log("before function");
  originalFunc();
  console.log("after function");
 }
}
var obj = {
 foo: function(){
  console.log(this.name);
 },
 name: "obj"
}

around(obj, 'foo', advice);

obj.foo();

round方法将处理过程与具体对象解耦;advice只要按照如下格式来书写,就可以达到around的效果

advice = function(originalFunc){
 return function() {
  //before
  originalFunc();
  //after
 }
}

Rerence