Arale aspect切面编程源码解析

来源:互联网 发布:js encoder在线编码器 编辑:程序博客网 时间:2024/06/06 19:57

切面编程能让你有效的控制方法的执行顺序。举个例子:

var Dialog = Base.extend({    ...    show: function() {        console.log(2);        this.element.show();    },    ...});var dialog = new Dialog();dialog.before('show', function() {    console.log(1);});dialog.after('show', function() {    console.log(3);});dialog.show(); // ==> 1, 2, 3

这里有一个需要注意的点就是,如果before方法返回的值为false,那么函数本身以及after方法的回调将不再执行。

var Dialog = Base.extend({    ...    show: function() {        console.log(2);        this.element.show();    },    ...});var dialog = new Dialog();dialog.before('show', function() {    console.log(1);    return false;});dialog.after('show', function() {    console.log(3);});dialog.show(); // ==> 1

其源码注释如下。因为这里的aspect是给Base类使用的,Base继承了Events,所以它有on,trigger等方法。

// this指向Base实例// 在指定方法执行前,先执行 callback// context是callback的执行环境exports.before = function(methodName, callback, context) {return weave.call(this, 'before', methodName, callback, context);};// 在指定方法执行后,再执行 callbackexports.after = function(methodName, callback, context) {return weave.call(this, 'after', methodName, callback, context);};// Helpers// -------// 以空格来分隔方法名var eventSplitter = /\s+/;function weave(when, methodName, callback, context) {// 将方法名转化为数组var names = methodName.split(eventSplitter);var name, method;while (name = names.shift()) {method = getMethod(this, name);// 如果没有wrap则执行wrapif (!method.__isAspected) {wrap.call(this, name);}// 继承了Eventsthis.on(when + ':' + name, callback, context);}return this;}// 从host宿主中取得方法名对应的方法(若是取不到则做报错处理)function getMethod(host, methodName) {var method = host[methodName];if (!method) {throw new Error('Invalid method name: ' + methodName);}return method;}// wrap方法function wrap(methodName) {// 保存方法名对应的方法var old = this[methodName];// 重新定义该方法this[methodName] = function() {var args = Array.prototype.slice.call(arguments);var beforeArgs = ['before:' + methodName].concat(args);// prevent if trigger return false// 如果before方法返回了false,那么就不再执行原方法以及after后的方法if (this.trigger.apply(this, beforeArgs) === false) return;var ret = old.apply(this, arguments);// 将原方法执行后的返回值也传给after后的执行的方法var afterArgs = ['after:' + methodName, ret].concat(args);this.trigger.apply(this, afterArgs);return ret;};// 给对应的方法名传递特殊参数,防止二次wrapthis[methodName].__isAspected = true;}


0 0
原创粉丝点击