2009-06-17 18 views

回答

30

以下是我發現至今:

  • dotvoid的實現,簡潔的語法,很好用,文章是爲什麼/如何使用給定的代碼,支持引進一個很好的介紹,但被竊聽,
  • 道場有什麼似乎是一個很好的內置實施dojoxhere是如何使用它的一個很好的介紹,
  • 沒有的jQuery,jquery-aop插件,用粗糙的語法,傳遞對象和方法在一個javascript對象中,
  • AspectJS具有更爲粗糙語法(需要傳遞切入點作爲參數的類型,以一個單一的方法)

就像我說的,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; 
     } 
} 
+0

發現功能的代碼以某種方式在Internet Explorer中工作嗎?由於我的測試失敗,我搜索了一下,似乎IE沒有「原型」屬性... – 2009-06-29 13:08:19

+0

我一直在IE7上對此進行測試。工作正常。較低版本未經測試。 – glmxndr 2009-06-29 13:44:23

13

您看過 https://github.com/cujojsmeld.jsaop.js

除了針對高級Javascript程序員的其他一些有用的東西外,SpringSource還提供了AOP功能。

免責聲明:我爲SpringSource工作。

3

基於dotvoid解決方案,我爲自己的項目需求創建了自己的JS AOP版本。 我基本上想要最小化方面設置成本,所以我在 Function.prototype添加了方面設置功能。

Function.prototype.applyBefore = function (aspect, targetFuncNames) { 
.... 
} 

我還需要支持aync回調,比如支持某些方法的驗證和授權。 例如:

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; 
     }; 
    } 
}; 

全面實施可以在http://www.jeffjin.net/aop-with-javascript