2009-06-17 1 views

Trả lời

30

Dưới đây là những gì tôi tìm thấy cho đến nay:

thực hiện
  • dotvoid 's, cú pháp trong sạch, tốt đẹp để sử dụng, bài viết là một giới thiệu tốt về việc tại sao/làm thế nào để sử dụng mã nhất định, hỗ trợ giới thiệu, nhưng được nghe trộm,
  • Dojo có gì có vẻ được một tốt built-in thực hiện trong dojox, here là một giới thiệu tốt đẹp về cách sử dụng nó,
  • có một plugin cho jQuery, jquery-aop, với một cú pháp thô, đi qua đối tượng và phương thức trong đối tượng javascript,
  • AspectJS với một cú pháp thậm chí thô (cần phải vượt qua loại pointcut như các đối số đến một phương pháp đơn)

Như tôi đã nói, mã dotvoid đã không làm việc. tôi sửa chữa một chút và có cái gì đó dường như làm việc tốt hơn:

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

Liệu mã bằng cách nào đó làm việc trong Internet Explorer? Khi các bài kiểm tra của tôi thất bại, tôi đã lẩn tránh và dường như IE không có "nguyên mẫu" -property ... –

+0

Tôi đã chạy thử nghiệm về điều này trên IE7. Hoạt động tốt. Mặc dù các phiên bản thấp hơn chưa được kiểm tra. – glmxndr

+1

2014: Tôi thấy khuôn khổ này vẫn còn rất tích cực [jsAspect] (https://github.com/antivanov/jsAspect) có vẻ như làm những gì AOP nên làm! –

13

Bạn đã thấy meld.jsaop.js từ https://github.com/cujojs?

SpringSource cung cấp chức năng AOP ở đó, ngoài một loạt những thứ hữu ích khác cho người lập trình Javascript nâng cao.

Tuyên bố từ chối: Tôi làm việc cho SpringSource.

+0

Đó là một câu hỏi khá cũ ... nhưng cảm ơn cho việc bổ sung. – glmxndr

3

Dựa trên giải pháp dotvoid, tôi đã tạo phiên bản JS AOP của riêng mình cho các nhu cầu dự án của riêng mình. Tôi về cơ bản muốn giảm thiểu chi phí thiết lập khía cạnh, vì vậy tôi đã thêm chức năng thiết lập khía cạnh tại Function.prototype.

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

Tôi cũng cần hỗ trợ gọi lại đồng bộ hóa, chẳng hạn như hỗ trợ xác thực và ủy quyền cho một số phương pháp nhất định. Ví dụ:

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(); 

Để thực hiện điều này, tôi cần phải chạy an ninh và và tiếp tục sau khi thành công hoặc dừng thực hiện trên thất bại.

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

Full thi thể được tìm thấy tại http://www.jeffjin.net/aop-with-javascript