Javascript的AOP库
你使用哪个Javascript AOP库,它的主要特点是什么?
这是我到目前为止发现的:
- dotvoid的实现,干净的语法,很好用,文章是一个很好的介绍为什么/如何使用给定的代码,支持引入,但是被窃听,
- Dojo在dojox中似乎是一个很好的内置实现, 这里有一个很好的介绍如何使用它,
- 有一个jQuery插件, jquery-aop ,使用粗糙的语法,在javascript对象中传递对象和方法,
- AspectJS使用更粗糙的语法(需要将切入点types作为parameter passing给单个方法)
就像我说的,dotvoid的代码不起作用。 我纠正了一些,并得到了一些似乎更好的工作:
InvalidAspect = new Error("Missing a valid aspect. Aspect is not a function."); InvalidObject = new Error("Missing valid object or an array of valid objects."); InvalidMethod = new Error("Missing valid method to apply aspect on."); function doBefore(beforeFunc,func){ return function(){ beforeFunc.apply(this,arguments); return func.apply(this,arguments); }; } function doAfter(func, afterFunc){ return function(){ var res = func.apply(this,arguments); afterFunc.apply(this,arguments); return res; }; } Aspects = function(){}; Aspects.prototype={ _addIntroduction : function(intro, obj){ for (var m in intro.prototype) { obj.prototype[m] = intro.prototype[m]; } }, addIntroduction : function(aspect, objs){ var oType = typeof(objs); if (typeof(aspect) != 'function') throw(InvalidAspect); if (oType == 'function'){ this._addIntroduction(aspect, objs); } else if (oType == 'object'){ for (var n = 0; n < objs.length; n++){ this._addIntroduction(aspect, objs[n]); } } else{ throw InvalidObject; } }, addBefore : function(aspect, obj, funcs){ var fType = typeof(funcs); if (typeof(aspect) != 'function') throw(InvalidAspect); if (fType != 'object') funcs = Array(funcs); for (var n = 0; n < funcs.length; n++){ var fName = funcs[n]; var old = obj.prototype[fName]; if (!old) throw InvalidMethod; var res = doBefore(aspect,old) obj.prototype[fName] = res; } }, addAfter : function(aspect, obj, funcs) { if (typeof(aspect) != 'function') throw InvalidAspect; if (typeof(funcs) != 'object') funcs = Array(funcs); for (var n = 0; n < funcs.length; n++) { var fName = funcs[n]; var old = obj.prototype[fName]; if (!old) throw InvalidMethod; var res = doAfter(old,aspect); obj.prototype[fName] = res; } }, addAround : function(aspect, obj, funcs){ if (typeof(aspect) != 'function') throw InvalidAspect; if (typeof(funcs) != 'object') funcs = Array(funcs); for (var n = 0; n < funcs.length; n++) { var fName = funcs[n]; var old = obj.prototype[fName]; if (!old) throw InvalidMethod; var res = aspect(old); obj.prototype[fName] = res; } return true; } }
你有没有从https://github.com/cujojs看到;meld.js
和aop.js
?
除了针对高级Javascript程序员的其他一些有用的东西,SpringSource还提供了AOPfunction。
免责声明 :我为SpringSource工作。
基于dotvoid解决scheme,我为自己的项目需要创build了自己的JS AOP版本。 我基本上想要最大限度地减less方面设置成本,所以我在Function.prototype添加了方面设置function。
Function.prototype.applyBefore = function (aspect, targetFuncNames) { .... }
我还需要支持aynccallback,比如支持某些方法的authentication和授权。 例如:
var authenticateAspect = function (error, success, context, args) { logger.log('authenticate (applyBefore async) aspect is being called'); var request = $.ajax({ url: "http://localhost/BlogWeb/api/user/authenticate", type: "GET", data: { username:'jeff', pwd:'jeff' }, success: function (data) { if (data) { success(); } else { error(); } }, error: error }); return request; }; Person.applyBefore(authenticateAspect, 'sendNotification'); var p1 = new Person(); p1.sendNotification();
为了实现这一点,我需要运行安全性,并继续成功或停止执行失败。
var invalidAspect = new Error("Missing a valid aspect. Aspect is not a function."), invalidMethod = new Error("Missing valid method to apply aspect on."); ///Parameters: aspect - defines the methods we want call before or/and /// after each method call ob target obejct /// targetFuncNames - target function names to apply aspects ///Return: it should return a new object with all aspects setup on target object Function.prototype.applyBefore = function (aspect, targetFuncNames) { if (typeof (aspect) != 'function') throw invalidAspect; if (typeof (targetFuncNames) != 'object') targetFuncNames = Array(targetFuncNames); var targetObj = this; //error handling function // Copy the properties over onto the new prototype for (var i = 0, len = targetFuncNames.length; i < len; i++) { var funcName = targetFuncNames[i]; var targetFunc = targetObj.prototype[funcName]; if (!targetFunc) throw invalidMethod; targetObj.prototype[funcName] = function () { var self = this, args = arguments; var success = function() { return targetFunc.apply(self, args); }; var error = function () { logger.log('applyBefore aspect failed to pass'); //log the error and throw new error throw new Error('applyBefore aspect failed to pass'); }; var aspectResult = aspect.apply(null, Array.prototype.concat([error, success, self], args)); return aspectResult; }; } };